diff options
| author | Louis Burda <quent.burda@gmail.com> | 2022-11-20 01:35:41 +0100 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2022-11-20 01:35:53 +0100 |
| commit | 5c2cb697aa8d03eed27b45f8dc67957c45a3d722 (patch) | |
| tree | 056e08b0e4d4aa0d6f65f84043beb151d6c6245f /src | |
| parent | 12a423434352af137bda357001ac824aa23fdf77 (diff) | |
| download | sxkbd-5c2cb697aa8d03eed27b45f8dc67957c45a3d722.tar.gz sxkbd-5c2cb697aa8d03eed27b45f8dc67957c45a3d722.zip | |
Onboard neopixel led support
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.c | 37 | ||||
| -rw-r--r-- | src/neopix.c | 22 | ||||
| -rw-r--r-- | src/neopix.h | 22 | ||||
| -rw-r--r-- | src/ws2812.pio | 48 | ||||
| -rw-r--r-- | src/ws2812.pio.h | 58 |
5 files changed, 168 insertions, 19 deletions
@@ -1,12 +1,14 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <sys/types.h> #include "bsp/board.h" #include "tusb.h" +#include "neopix.h" /* Blink pattern - * - 250 ms : device not mounted + * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ @@ -18,19 +20,20 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; +static struct neopix onboard_led; + void led_blinking_task(void); -/*------------- MAIN -------------*/ int main(void) { board_init(); - // init device stack on configured roothub port + neopix_init(&onboard_led, pio0, 0, 25); + tud_init(BOARD_TUD_RHPORT); - while (1) - { - tud_task(); // tinyusb device task + while (1) { + tud_task(); led_blinking_task(); } @@ -78,7 +81,6 @@ void tud_resume_cb(void) 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) { - // TODO not Implemented (void) itf; (void) report_id; (void) report_type; @@ -93,27 +95,24 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, 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) { - // This example doesn't use multiple report and report ID (void) itf; (void) report_id; (void) report_type; - // echo back anything we received from host tud_hid_report(0, buffer, bufsize); } -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -void led_blinking_task(void) +void +led_blinking_task(void) { static uint32_t start_ms = 0; - static bool led_state = false; + static bool state = false; - // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; + if (board_millis() - start_ms < blink_interval_ms) + return; + + neopix_put(&onboard_led, neopix_u32rgb(255 * state, 0, 0)); - board_led_write(led_state); - led_state = 1 - led_state; // toggle + start_ms += blink_interval_ms; + state ^= true; } diff --git a/src/neopix.c b/src/neopix.c new file mode 100644 index 0000000..ddc78a3 --- /dev/null +++ b/src/neopix.c @@ -0,0 +1,22 @@ +#include "hardware/pio.h" + +#include "neopix.h" +#include "ws2812.pio.h" + +void +neopix_init(struct neopix *pix, PIO pio, uint sm, uint pin) +{ + uint offset; + + pix->sm = sm; + pix->pio = pio; + pix->pin = pin; + offset = pio_add_program(pix->pio, &ws2812_program); + ws2812_program_init(pix->pio, pix->sm, offset, + pix->pin, 800000, false); +} + +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 new file mode 100644 index 0000000..8b01038 --- /dev/null +++ b/src/neopix.h @@ -0,0 +1,22 @@ +#include "hardware/pio.h" +#include "hardware/gpio.h" + +struct neopix { + PIO pio; + uint sm; + uint pin; +}; + +void neopix_init(struct neopix *pix, PIO pio, uint sm, 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/ws2812.pio b/src/ws2812.pio new file mode 100644 index 0000000..ae19a6b --- /dev/null +++ b/src/ws2812.pio @@ -0,0 +1,48 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program ws2812 +.side_set 1 + +.define public T1 2 +.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 + jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse +do_one: + jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse +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 new file mode 100644 index 0000000..e95f7ea --- /dev/null +++ b/src/ws2812.pio.h @@ -0,0 +1,58 @@ +// -------------------------------------------------- // +// 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 |
