summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt25
-rw-r--r--main.c49
-rw-r--r--ws2812.pio85
4 files changed, 161 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..01e12f3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+generated/
+build/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..ec8beae
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.13)
+include(/home/dwlr/projects/current/rp2040/pico-sdk/pico_sdk_init.cmake)
+
+pico_sdk_init()
+project(eeprom2blk)
+enable_language(C CXX ASM)
+
+add_executable(eeprom2blk main.c)
+
+set_source_files_properties(main.c PROPERTIES
+ COMPILE_FLAGS -Wall -Wextra -pedantic
+ C_STANDARD 90
+)
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/generated)
+pico_generate_pio_header(eeprom2blk ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/generated)
+
+target_link_libraries(eeprom2blk pico_stdlib hardware_pio hardware_dma)
+
+# change default stdout
+pico_enable_stdio_usb(eeprom2blk 1)
+pico_enable_stdio_uart(eeprom2blk 0)
+
+# create map/bin/hex/uf2 file in addition to ELF.
+pico_add_extra_outputs(eeprom2blk)
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..8a7250e
--- /dev/null
+++ b/main.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "pico/stdlib.h"
+#include "hardware/gpio.h"
+#include "hardware/pio.h"
+#include "hardware/clocks.h"
+
+#include "ws2812.pio.h"
+
+
+#define PIN_RGB 16
+
+
+int main(void)
+{
+ stdio_init_all();
+
+ gpio_init(PIN_RGB);
+ gpio_set_dir(PIN_RGB, GPIO_OUT);
+ gpio_put(PIN_RGB, 1);
+
+ PIO pio = pio0;
+ int sm = 0; // XXX: ???
+ uint32_t offset = pio_add_program(pio, &ws2812_program);
+
+ ws2812_program_init(pio, sm, offset, PIN_RGB, 800000, false);
+
+ uint32_t col = 0;
+ pio_sm_put_blocking(pio0, 0, col << 8u);
+
+ sleep_ms(1000);
+
+ col = 0x0000FF;
+ printf("Hell, world...\n");
+ while(1)
+ {
+ pio_sm_put_blocking(pio0, 0, col);
+ col = col << 8u;
+ if(!col) col = 0x0000FF;
+ sleep_ms(250);
+ }
+
+ return 0;
+}
diff --git a/ws2812.pio b/ws2812.pio
new file mode 100644
index 0000000..3c31fd6
--- /dev/null
+++ b/ws2812.pio
@@ -0,0 +1,85 @@
+;
+; 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);
+}
+%}
+
+.program ws2812_parallel
+
+.define public T1 2
+.define public T2 5
+.define public T3 3
+
+.wrap_target
+ out x, 32
+ mov pins, !null [T1-1]
+ mov pins, x [T2-1]
+ mov pins, null [T3-2]
+.wrap
+
+% c-sdk {
+#include "hardware/clocks.h"
+
+static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) {
+ for(uint i=pin_base; i<pin_base+pin_count; i++) {
+ pio_gpio_init(pio, i);
+ }
+ pio_sm_set_consecutive_pindirs(pio, sm, pin_base, pin_count, true);
+
+ pio_sm_config c = ws2812_parallel_program_get_default_config(offset);
+ sm_config_set_out_shift(&c, true, true, 32);
+ sm_config_set_out_pins(&c, pin_base, pin_count);
+ sm_config_set_set_pins(&c, pin_base, pin_count);
+ sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
+
+ int cycles_per_bit = ws2812_parallel_T1 + ws2812_parallel_T2 + ws2812_parallel_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);
+}
+%}