commit 0392766bc379448c907de2bce45d6b57621d95b5
parent 6defee37f9939991bbf3152e2cd4e18593baa541
Author: Louis Burda <quent.burda@gmail.com>
Date: Fri, 2 Dec 2022 16:06:32 +0100
Added split uart support based on chibios impl
Diffstat:
19 files changed, 410 insertions(+), 356 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,3 +1,4 @@
.build
.cache
compile_commands.json
+src/*.pio.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -10,12 +10,17 @@ family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
add_executable(${PROJECT})
+pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/ws2812.pio)
+pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/uart_tx.pio)
+pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/uart_rx.pio)
+
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/ws2812.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/led.c
${CMAKE_CURRENT_SOURCE_DIR}/src/matrix.c
${CMAKE_CURRENT_SOURCE_DIR}/src/keymap.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_stdio.c
@@ -53,3 +58,6 @@ target_compile_options(${PROJECT} PRIVATE
family_configure_target(${PROJECT})
family_add_default_example_warnings(${PROJECT})
suppress_tinyusb_warnings()
+
+#pico_enable_stdio_usb(${PROJECT} 1)
+pico_enable_stdio_uart(${PROJECT} 0)
diff --git a/extra/tinyusb.diff b/extra/tinyusb.diff
@@ -0,0 +1,31 @@
+diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c
+index 90e2192c0..6a2735eaf 100644
+--- a/hw/bsp/rp2040/family.c
++++ b/hw/bsp/rp2040/family.c
+@@ -118,7 +118,7 @@ void stdio_rtt_init(void)
+
+ #endif
+
+-#ifdef UART_DEV
++#if defined(UART_DEV) && defined(LIB_PICO_STDIO_UART)
+ static uart_inst_t *uart_inst;
+ #endif
+
+@@ -188,7 +188,7 @@ uint32_t board_button_read(void)
+
+ int board_uart_read(uint8_t* buf, int len)
+ {
+-#ifdef UART_DEV
++#if defined(UART_DEV) && defined(LIB_PICO_STDIO_UART)
+ for(int i=0;i<len;i++) {
+ buf[i] = uart_getc(uart_inst);
+ }
+@@ -201,7 +201,7 @@ int board_uart_read(uint8_t* buf, int len)
+
+ int board_uart_write(void const * buf, int len)
+ {
+-#ifdef UART_DEV
++#if defined(UART_DEV) && defined(LIB_PICO_STDIO_UART)
+ char const* bufch = (char const*) buf;
+ for(int i=0;i<len;i++) {
+ uart_putc(uart_inst, bufch[i]);
diff --git a/src/board.h b/src/board.h
@@ -1,8 +1,6 @@
#pragma once
-#include "neopix.h"
-
-#define ONBOARD_LED_PIN 25
+#include <stdint.h>
#define REPORT_ID_MIN REPORT_ID_KEYBOARD
enum {
@@ -12,7 +10,5 @@ enum {
REPORT_ID_MAX
};
-extern struct neopix onboard_led;
-
extern const uint32_t **keymap_layers;
diff --git a/src/led.c b/src/led.c
@@ -0,0 +1,55 @@
+#include "led.h"
+#include "ws2812.h"
+#include "util.h"
+
+#include "bsp/board.h"
+
+#define ONBOARD_LED_PIN 25
+
+static struct ws2812 onboard_led;
+
+int led_mode;
+bool led_reset;
+uint32_t led_blink_ms;
+uint32_t led_rgb;
+
+void
+led_init(void)
+{
+ led_reset = true;
+ led_mode = LED_ON;
+ led_rgb = WS2812_U32RGB(100, 100, 100);
+ ws2812_init(&onboard_led, pio0, ONBOARD_LED_PIN);
+}
+
+void
+led_task(void)
+{
+ static uint32_t start_ms = 0;
+ static bool state = false;
+
+ switch (led_mode) {
+ case LED_OFF:
+ if (led_reset)
+ ws2812_put(&onboard_led, 0);
+ break;
+ case LED_ON:
+ if (led_reset)
+ ws2812_put(&onboard_led, led_rgb);
+ break;
+ case LED_BLINK:
+ if (led_reset)
+ start_ms = board_millis();
+
+ if (board_millis() - start_ms < led_blink_ms)
+ return;
+ start_ms += led_blink_ms;
+
+ state = !state;
+ ws2812_put(&onboard_led, state ? led_rgb : 0);
+ break;
+ }
+
+ led_reset = false;
+}
+
diff --git a/src/led.h b/src/led.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+enum {
+ LED_OFF,
+ LED_ON,
+ LED_BLINK
+};
+
+extern int led_mode;
+extern bool led_reset;
+extern uint32_t led_blink_ms;
+extern uint32_t led_rgb;
+
+void led_init(void);
+void led_task(void);
diff --git a/src/main.c b/src/main.c
@@ -2,9 +2,10 @@
#include "usb_stdio.h"
#include "matrix.h"
#include "split.h"
+#include "led.h"
#include "hid.h"
#include "keymap.h"
-#include "neopix.h"
+#include "ws2812.h"
#include "util.h"
#include "hardware/gpio.h"
@@ -19,42 +20,26 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <sys/types.h>
-
-enum {
- BLINK_NOT_MOUNTED = 250,
- BLINK_MOUNTED = 1000,
- BLINK_SUSPENDED = 2500,
-};
bool send_hid_report(int id, bool state);
-void blink_task(void);
-
-static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
-
static bool hit_state = false;
-
const uint32_t **keymap_layers = keymap_layers_de;
-struct neopix onboard_led;
-
int
main(void)
{
board_init();
tud_init(BOARD_TUD_RHPORT);
usb_stdio_init();
- neopix_init(&onboard_led, ONBOARD_LED_PIN);
+ led_init();
matrix_init();
split_init();
//hid_init();
- ASSERT(1 == 0);
-
while (true) {
tud_task();
- blink_task();
+ led_task();
split_task();
//hid_task();
}
@@ -65,25 +50,34 @@ main(void)
void
tud_mount_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ led_rgb = WS2812_U32RGB(100, 0, 100);
+ led_mode = LED_ON;
+ led_reset = true;
}
void
tud_umount_cb(void)
{
- blink_interval_ms = BLINK_NOT_MOUNTED;
+ led_blink_ms = 500;
+ led_rgb = WS2812_U32RGB(100, 100, 100);
+ led_mode = LED_BLINK;
+ led_reset = true;
}
void
tud_suspend_cb(bool remote_wakeup_en)
{
- blink_interval_ms = BLINK_SUSPENDED;
+ led_rgb = WS2812_U32RGB(100, 100, 100);
+ led_mode = LED_ON;
+ led_reset = true;
}
void
tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ led_rgb = WS2812_U32RGB(100, 0, 100);
+ led_mode = LED_ON;
+ led_reset = true;
}
void
@@ -94,6 +88,7 @@ tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
void
tud_cdc_rx_cb(uint8_t itf)
{
+ printf("ALIVE\n\r");
}
uint16_t
@@ -201,20 +196,3 @@ send_hid_report_timed(void)
send_hid_report(REPORT_ID_MIN, hit_state);
}
-
-void
-blink_task(void)
-{
- static uint32_t start_ms = 0;
- static bool state = false;
-
- if (board_millis() - start_ms < blink_interval_ms)
- return;
- start_ms += blink_interval_ms;
-
- DEBUG("blink");
-
- state ^= true;
- neopix_put(&onboard_led, neopix_u32rgb(255 * state, 0, 255 * state));
-}
-
diff --git a/src/neopix.c b/src/neopix.c
@@ -1,27 +0,0 @@
-#include "neopix.h"
-#include "ws2812.pio.h"
-#include "util.h"
-
-#include "hardware/pio.h"
-
-void
-neopix_init(struct neopix *pix, uint pin)
-{
- uint offset;
- int sm;
-
- 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,
- pix->pin, 800000, false);
- pix->init = true;
-}
-
-void
-neopix_put(struct neopix *pix, uint32_t rgb) {
- pio_sm_put_blocking(pix->pio, pix->sm, rgb << 8u);
-}
diff --git a/src/neopix.h b/src/neopix.h
@@ -1,27 +0,0 @@
-#pragma once
-
-#include "hardware/pio.h"
-#include "hardware/gpio.h"
-
-#include <stdbool.h>
-
-struct neopix {
- PIO pio;
- uint sm;
- uint pin;
- bool init;
-};
-
-void neopix_init(struct neopix *pix, uint pin);
-void neopix_put(struct neopix *pix, uint32_t rgb);
-
-inline uint32_t
-neopix_u32rgb(uint8_t r, uint8_t g, uint8_t b) {
- uint32_t rgb;
-
- rgb = ((uint32_t) r) << 8;
- rgb |= ((uint32_t) g) << 16;
- rgb |= ((uint32_t) b) << 0;
-
- return rgb;
-}
diff --git 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;
+ }
+ }
}
diff --git a/src/split.h b/src/split.h
@@ -1,4 +1,5 @@
#pragma once
void split_init(void);
+void split_test(void);
void split_task(void);
diff --git a/src/uart_rx.pio b/src/uart_rx.pio
@@ -0,0 +1,22 @@
+.program uart_rx
+
+.wrap_target
+start:
+ wait 0 pin, 0 [6] ; wait for START bit
+
+ set x, 7 [4] ; read 8 DATA bits and offset
+ ; clock for better readings
+bitloop:
+ in pins, 1
+ jmp x--, bitloop [6]
+
+ jmp pin, outb ; got STOP bit, output byte
+
+error:
+ irq wait 0 ; no STOP bit,
+ wait 1 pin, 0 ; set err IRQ and await reset
+ jmp start
+
+outb:
+ push block
+.wrap
diff --git a/src/uart_tx.pio b/src/uart_tx.pio
@@ -0,0 +1,10 @@
+.program uart_tx
+.side_set 1 opt pindirs
+
+.wrap_target
+ pull block side 1 [7] ; IDLE / STOP bit
+ set x, 7 side 0 [7] ; START bit
+bitloop:
+ out pindirs, 1 ; 8 DATA bits
+ jmp x--, bitloop [6]
+.wrap
diff --git a/src/util.c b/src/util.c
@@ -1,7 +1,9 @@
#include "util.h"
#include "board.h"
-#include "neopix.h"
+#include "led.h"
+#include "ws2812.h"
+#include "pico/stdio.h"
#include "tusb.h"
#include "bsp/board.h"
#include "tusb_config.h"
@@ -28,27 +30,11 @@ panic_task(const char *fmtstr, va_list ap, uint32_t sleep_ms)
va_copy(cpy, ap);
vprintf(fmtstr, cpy);
printf("\n\r");
+ stdio_flush();
start_ms += sleep_ms;
}
-static void
-blink_task(struct neopix *pix, uint32_t blink_ms)
-{
- static uint32_t start_ms = 0;
- static bool led_state = false;
-
- if (!start_ms) start_ms = board_millis();
-
- 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;
-}
-
void
__attribute__ ((format (printf, 2, 3)))
stdio_log(int level, const char *fmtstr, ...)
@@ -65,21 +51,25 @@ stdio_log(int level, const char *fmtstr, ...)
vprintf(fmtstr, ap);
va_end(ap);
printf("\n\r");
+ stdio_flush();
}
void
-__attribute__((format(printf, 1, 2)))
-blink_panic(const char *fmtstr, ...)
+__attribute__((format(printf, 3, 4)))
+blink_panic(uint32_t blink_ms, uint32_t rgb, const char *fmtstr, ...)
{
va_list ap;
va_start(ap, fmtstr);
+ led_blink_ms = blink_ms;
+ led_rgb = rgb;
+ led_mode = LED_BLINK;
+
while (1) {
tud_task();
panic_task(fmtstr, ap, 1000);
- if (onboard_led.init)
- blink_task(&onboard_led, 200);
+ led_task();
}
va_end(ap);
diff --git a/src/util.h b/src/util.h
@@ -1,6 +1,9 @@
#pragma once
+#include "ws2812.h"
+
#include <stdbool.h>
+#include <stdint.h>
#include <stdarg.h>
#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
@@ -10,12 +13,17 @@
#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 PANIC(...) blink_panic(200, WS2812_U32RGB(255, 0, 0), __VA_ARGS__);
#define ASSERT(cond) do { \
- if (!(cond)) blink_panic("Assertion failed: (%s) in %s:%i", \
+ if (!(cond)) PANIC("Assertion failed: (%s) in %s:%i", \
#cond, __FILE__, __LINE__); \
} while (0)
+#define CLAIM_UNUSED_SM(pio) ({ \
+ int tmp = pio_claim_unused_sm(pio, false); \
+ ASSERT(tmp >= 0); \
+ (uint) tmp; })
+
enum {
LOG_NONE,
LOG_ERR,
@@ -26,6 +34,6 @@ enum {
void stdio_log(int loglevel, const char *fmtstr, ...);
-void blink_panic(const char *fmtstr, ...);
+void blink_panic(uint32_t blink_ms, uint32_t rgb, const char *fmtstr, ...);
extern int loglevel;
diff --git a/src/ws2812.c b/src/ws2812.c
@@ -0,0 +1,43 @@
+#include "ws2812.h"
+#include "ws2812.pio.h"
+#include "util.h"
+
+#include "hardware/pio.h"
+#include "hardware/clocks.h"
+
+#define CYCLES_PER_BIT (ws2812_T1 + ws2812_T2 + ws2812_T3)
+
+void
+ws2812_init(struct ws2812 *pix, PIO pio, uint pin)
+{
+ pio_sm_config config;
+ uint offset;
+ uint sm;
+
+ pix->pio = pio;
+ pix->pin = pin;
+
+ sm = CLAIM_UNUSED_SM(pio);
+ pix->sm = sm;
+
+ pio_gpio_init(pio, pin);
+ pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
+
+ offset = pio_add_program(pix->pio, &ws2812_program);
+ config = ws2812_program_get_default_config(offset);
+ sm_config_set_sideset_pins(&config, pin);
+ sm_config_set_out_shift(&config, false, true, 24);
+ sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_TX);
+ sm_config_set_clkdiv(&config,
+ (float) clock_get_hz(clk_sys) / (800000 * CYCLES_PER_BIT));
+
+ pio_sm_init(pio, sm, offset, &config);
+ pio_sm_set_enabled(pio, sm, true);
+
+ pix->init = true;
+}
+
+void
+ws2812_put(struct ws2812 *pix, uint32_t rgb) {
+ pio_sm_put_blocking(pix->pio, pix->sm, rgb << 8u);
+}
diff --git a/src/ws2812.h b/src/ws2812.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "hardware/pio.h"
+#include "hardware/gpio.h"
+
+#include <stdbool.h>
+
+#define _WS2812_U8(v, s) (((uint32_t) (v) & 0xFF) << s)
+#define WS2812_U32RGB(r, g, b) \
+ (_WS2812_U8(b, 0) | _WS2812_U8(r, 8) | _WS2812_U8(g, 16))
+
+struct ws2812 {
+ PIO pio;
+ uint sm;
+ uint pin;
+ bool init;
+};
+
+void ws2812_init(struct ws2812 *pix, PIO pio, uint pin);
+void ws2812_put(struct ws2812 *pix, uint32_t rgb);
diff --git a/src/ws2812.pio b/src/ws2812.pio
@@ -1,9 +1,3 @@
-;
-; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
-;
-; SPDX-License-Identifier: BSD-3-Clause
-;
-
.program ws2812
.side_set 1
@@ -11,10 +5,6 @@
.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
@@ -24,25 +14,3 @@ do_one:
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);
-}
-%}
diff --git a/src/ws2812.pio.h b/src/ws2812.pio.h
@@ -1,58 +0,0 @@
-// -------------------------------------------------- //
-// This file is autogenerated by pioasm; do not edit! //
-// -------------------------------------------------- //
-
-#if !PICO_NO_HARDWARE
-#include "hardware/pio.h"
-#endif
-
-// ------ //
-// ws2812 //
-// ------ //
-
-#define ws2812_wrap_target 0
-#define ws2812_wrap 3
-
-#define ws2812_T1 2
-#define ws2812_T2 5
-#define ws2812_T3 3
-
-static const uint16_t ws2812_program_instructions[] = {
- // .wrap_target
- 0x6221, // 0: out x, 1 side 0 [2]
- 0x1123, // 1: jmp !x, 3 side 1 [1]
- 0x1400, // 2: jmp 0 side 1 [4]
- 0xa442, // 3: nop side 0 [4]
- // .wrap
-};
-
-#if !PICO_NO_HARDWARE
-static const struct pio_program ws2812_program = {
- .instructions = ws2812_program_instructions,
- .length = 4,
- .origin = -1,
-};
-
-static inline pio_sm_config ws2812_program_get_default_config(uint offset) {
- pio_sm_config c = pio_get_default_sm_config();
- sm_config_set_wrap(&c, offset + ws2812_wrap_target, offset + ws2812_wrap);
- sm_config_set_sideset(&c, 1, false, false);
- return c;
-}
-
-#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 = ((float) clock_get_hz(clk_sys)) / (freq * (float) cycles_per_bit);
- sm_config_set_clkdiv(&c, div);
- pio_sm_init(pio, sm, offset, &c);
- pio_sm_set_enabled(pio, sm, true);
-}
-
-#endif