From 9ee030d1cc33d445ea749be943a0dae4d46182b0 Mon Sep 17 00:00:00 2001 From: MaartenS11 Date: Tue, 25 Mar 2025 10:19:22 +0100 Subject: [PATCH 1/3] Add basic neopixel support for Zephyr on the rpi pico --- platforms/Zephyr/boards/rpi_pico.overlay | 42 +++++++- platforms/Zephyr/prj.conf | 4 + src/Primitives/zephyr.cpp | 117 +++++++++++++++++++++-- 3 files changed, 153 insertions(+), 10 deletions(-) diff --git a/platforms/Zephyr/boards/rpi_pico.overlay b/platforms/Zephyr/boards/rpi_pico.overlay index 1b7b6ee8..28354687 100644 --- a/platforms/Zephyr/boards/rpi_pico.overlay +++ b/platforms/Zephyr/boards/rpi_pico.overlay @@ -1,6 +1,11 @@ #include "../app.overlay" +#include / { + aliases { + led-strip = &ws2812; + }; + zephyr,user { warduino-gpios = <&gpio0 0 0>, @@ -34,4 +39,39 @@ <&gpio0 28 0>, <&gpio0 29 0>; }; -}; +}; + +&pio1 { + status = "okay"; + + /* + * Need to put this on PIO1 as having this on PIO0 causes the GPIO hog to + * not work. + */ + pio-ws2812 { + compatible = "worldsemi,ws2812-rpi_pico-pio"; + status = "okay"; + pinctrl-0 = <&ws2812_pio1_default>; + pinctrl-names = "default"; + bit-waveform = <3>, <3>, <4>; + + ws2812: ws2812 { + status = "okay"; + gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + chain-length = <64>; + color-mapping = ; + reset-delay = <280>; + frequency = <800000>; + }; + }; +}; + +&pinctrl { + ws2812_pio1_default: ws2812_pio1_default { + ws2812 { + pinmux = ; + }; + }; +}; diff --git a/platforms/Zephyr/prj.conf b/platforms/Zephyr/prj.conf index c5107231..7087142e 100644 --- a/platforms/Zephyr/prj.conf +++ b/platforms/Zephyr/prj.conf @@ -30,3 +30,7 @@ CONFIG_CONSOLE_PUTCHAR_BUFSIZE=4096 CONFIG_POSIX_API=y CONFIG_MAIN_STACK_SIZE=8192 + +CONFIG_LOG=y +CONFIG_LED_STRIP=y +CONFIG_LED_STRIP_LOG_LEVEL_DBG=n \ No newline at end of file diff --git a/src/Primitives/zephyr.cpp b/src/Primitives/zephyr.cpp index 4a9303ee..11c0151d 100644 --- a/src/Primitives/zephyr.cpp +++ b/src/Primitives/zephyr.cpp @@ -32,7 +32,7 @@ #include "../Utils/util.h" #include "primitives.h" -#define ALL_PRIMITIVES 5 +#define ALL_PRIMITIVES 9 // Global index for installing primitives int prim_index = 0; @@ -262,6 +262,100 @@ def_prim(print_int, oneToNoneU32) { return true; } +#include +#define RGB(_r, _g, _b) { .r = (_r), .g = (_g), .b = (_b) } +static const struct device *const strip = DEVICE_DT_GET(DT_ALIAS(led_strip)); +const size_t strip_length = 64;//led_strip_length(device); +struct led_rgb pixels[strip_length] = {0}; + +void fun() { + size_t color = 0; + int rc; + + if (device_is_ready(strip)) { + printf("Found LED strip device %s\n", strip->name); + } else { + printf("LED strip device %s is not ready\n", strip->name); + return; + } + + printf("Displaying pattern on strip\n"); + const struct led_rgb colors[] = { + RGB(16, 0x00, 0x00), // red + RGB(0x00, 16, 0x00), // green + RGB(0x00, 0x00, 16), // blue + }; + size_t width = 3; + while (1) { + for (size_t cursor = 0; cursor < ARRAY_SIZE(pixels) - width + 1; cursor++) { + memset(&pixels, 0x00, sizeof(pixels)); + for (size_t i = 0; i < width; i++) { + memcpy(&pixels[cursor + i], &colors[color], sizeof(struct led_rgb)); + color = (color + 1) % ARRAY_SIZE(colors); + } + + printf("Update strip!\n"); + rc = led_strip_update_rgb(strip, pixels, strip_length); + if (rc) { + printf("couldn't update strip: %d", rc); + } + + k_sleep(K_MSEC(100)); + } + } +} + +def_prim(led_fun, NoneToNoneU32) { + fun(); + return true; +} + +def_prim(show_pixels, NoneToNoneU32) { + int rc = led_strip_update_rgb(strip, pixels, strip_length); + if (rc) { + printf("couldn't update strip: %d", rc); + } + return true; +} + +def_prim(set_pixel_color, fourToOneU32) { + uint8_t blue = arg0.uint32; + uint8_t green = arg1.uint32; + uint8_t red = arg2.uint32; + uint8_t index = arg3.uint32; + + led_rgb color = {.r = red, .g = green, .b= blue}; + memcpy(&pixels[index], &color, sizeof(struct led_rgb)); + pop_args(4); + return true; +} + +def_prim_serialize(set_pixel_color) { + for (int i = 0; i < strip_length; i++) { + auto *state = new IOStateElement(); + state->key = "n" + std::to_string(i); + state->output = true; + state->value = pixels[i].r << 16 | pixels[i].g << 8 | pixels[i].b; + external_state.push_back(state); + } +} + +def_prim_reverse(set_pixel_color) { + for (IOStateElement state : external_state) { + if (!state.output) { + continue; + } + + if (state.key[0] == 'n') { + int index = stoi(state.key.substr(1)); + pixels[index].r = ((uint32_t) state.value >> 16) & 0xff; + pixels[index].g = ((uint32_t) state.value >> 8) & 0xff; + pixels[index].b = state.value & 0xff; + invoke_primitive(m, "show_pixels"); + } + } +} + //------------------------------------------------------ // Installing all the primitives //------------------------------------------------------ @@ -272,6 +366,10 @@ void install_primitives() { install_primitive(chip_digital_write); install_primitive(chip_digital_read); install_primitive(print_int); + install_primitive(led_fun); + install_primitive(set_pixel_color); + install_primitive_reverse(set_pixel_color); + install_primitive(show_pixels); } //------------------------------------------------------ @@ -322,22 +420,23 @@ void restore_external_state(Module *m, // instructions such as call_indirect // maybe there should just be a function that checks if a certain function // is being called that handles all these cases? - if (opcode == 0x10) { // call opcode + /*if (opcode == 0x10) { // call opcode uint8_t *pc_copy = m->pc_ptr + 1; uint32_t fidx = read_LEB_32(&pc_copy); - if (fidx < m->import_count) { - for (auto &primitive : primitives) { - if (!strcmp(primitive.name, m->functions[fidx].import_field)) { + if (fidx < m->import_count) {*/ + for (int i = 0; i < ALL_PRIMITIVES; i++) { + auto primitive = primitives[i]; + printf("%s\n", primitive.name); + //if (!strcmp(primitive.name, m->functions[fidx].import_field)) { if (primitive.f_reverse) { debug("Reversing action for primitive %s\n", primitive.name); primitive.f_reverse(m, external_state); } - return; - } + //} } - } - } + /*} + }*/ } std::vector get_io_state(Module *m) { From eacd4f013fa6c3b2403e336a524e8b6e17c3a998 Mon Sep 17 00:00:00 2001 From: MaartenS11 Date: Tue, 25 Mar 2025 10:25:08 +0100 Subject: [PATCH 2/3] Minor cleanup --- src/Primitives/zephyr.cpp | 82 ++++++--------------------------------- 1 file changed, 12 insertions(+), 70 deletions(-) diff --git a/src/Primitives/zephyr.cpp b/src/Primitives/zephyr.cpp index 11c0151d..6cd9dad1 100644 --- a/src/Primitives/zephyr.cpp +++ b/src/Primitives/zephyr.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,7 @@ #include "../Utils/util.h" #include "primitives.h" -#define ALL_PRIMITIVES 9 +#define ALL_PRIMITIVES 7 // Global index for installing primitives int prim_index = 0; @@ -262,53 +263,9 @@ def_prim(print_int, oneToNoneU32) { return true; } -#include -#define RGB(_r, _g, _b) { .r = (_r), .g = (_g), .b = (_b) } -static const struct device *const strip = DEVICE_DT_GET(DT_ALIAS(led_strip)); +static const device *const strip = DEVICE_DT_GET(DT_ALIAS(led_strip)); const size_t strip_length = 64;//led_strip_length(device); -struct led_rgb pixels[strip_length] = {0}; - -void fun() { - size_t color = 0; - int rc; - - if (device_is_ready(strip)) { - printf("Found LED strip device %s\n", strip->name); - } else { - printf("LED strip device %s is not ready\n", strip->name); - return; - } - - printf("Displaying pattern on strip\n"); - const struct led_rgb colors[] = { - RGB(16, 0x00, 0x00), // red - RGB(0x00, 16, 0x00), // green - RGB(0x00, 0x00, 16), // blue - }; - size_t width = 3; - while (1) { - for (size_t cursor = 0; cursor < ARRAY_SIZE(pixels) - width + 1; cursor++) { - memset(&pixels, 0x00, sizeof(pixels)); - for (size_t i = 0; i < width; i++) { - memcpy(&pixels[cursor + i], &colors[color], sizeof(struct led_rgb)); - color = (color + 1) % ARRAY_SIZE(colors); - } - - printf("Update strip!\n"); - rc = led_strip_update_rgb(strip, pixels, strip_length); - if (rc) { - printf("couldn't update strip: %d", rc); - } - - k_sleep(K_MSEC(100)); - } - } -} - -def_prim(led_fun, NoneToNoneU32) { - fun(); - return true; -} +led_rgb pixels[strip_length] = {0}; def_prim(show_pixels, NoneToNoneU32) { int rc = led_strip_update_rgb(strip, pixels, strip_length); @@ -366,7 +323,6 @@ void install_primitives() { install_primitive(chip_digital_write); install_primitive(chip_digital_read); install_primitive(print_int); - install_primitive(led_fun); install_primitive(set_pixel_color); install_primitive_reverse(set_pixel_color); install_primitive(show_pixels); @@ -415,28 +371,14 @@ bool resolve_external_memory(char *symbol, Memory **val) { //------------------------------------------------------ void restore_external_state(Module *m, const std::vector &external_state) { - uint8_t opcode = *m->pc_ptr; - // TODO: Maybe primitives can also be called using the other call - // instructions such as call_indirect - // maybe there should just be a function that checks if a certain function - // is being called that handles all these cases? - /*if (opcode == 0x10) { // call opcode - uint8_t *pc_copy = m->pc_ptr + 1; - uint32_t fidx = read_LEB_32(&pc_copy); - if (fidx < m->import_count) {*/ - for (int i = 0; i < ALL_PRIMITIVES; i++) { - auto primitive = primitives[i]; - printf("%s\n", primitive.name); - //if (!strcmp(primitive.name, m->functions[fidx].import_field)) { - if (primitive.f_reverse) { - debug("Reversing action for primitive %s\n", - primitive.name); - primitive.f_reverse(m, external_state); - } - //} - } - /*} - }*/ + for (int i = 0; i < ALL_PRIMITIVES; i++) { + auto primitive = primitives[i]; + if (primitive.f_reverse) { + debug("Reversing action for primitive %s\n", + primitive.name); + primitive.f_reverse(m, external_state); + } + } } std::vector get_io_state(Module *m) { From 2c48fe72f1fda3300922aadc9e04dcfd7f891448 Mon Sep 17 00:00:00 2001 From: MaartenS11 Date: Fri, 28 Mar 2025 16:58:55 +0100 Subject: [PATCH 3/3] Make show_pixels reversible --- src/Primitives/zephyr.cpp | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Primitives/zephyr.cpp b/src/Primitives/zephyr.cpp index 6cd9dad1..d73dfa9f 100644 --- a/src/Primitives/zephyr.cpp +++ b/src/Primitives/zephyr.cpp @@ -266,15 +266,46 @@ def_prim(print_int, oneToNoneU32) { static const device *const strip = DEVICE_DT_GET(DT_ALIAS(led_strip)); const size_t strip_length = 64;//led_strip_length(device); led_rgb pixels[strip_length] = {0}; +led_rgb pixels_shown[strip_length] = {0}; def_prim(show_pixels, NoneToNoneU32) { - int rc = led_strip_update_rgb(strip, pixels, strip_length); + memcpy(pixels_shown, pixels, strip_length * sizeof(led_rgb)); + int rc = led_strip_update_rgb(strip, pixels_shown, strip_length); if (rc) { printf("couldn't update strip: %d", rc); } return true; } +def_prim_serialize(show_pixels) { + for (int i = 0; i < strip_length; i++) { + auto *state = new IOStateElement(); + state->key = "n" + std::to_string(i); + state->output = true; + state->value = pixels_shown[i].r << 16 | pixels_shown[i].g << 8 | pixels_shown[i].b; + external_state.push_back(state); + } +} + +def_prim_reverse(show_pixels) { + for (IOStateElement state : external_state) { + if (!state.output) { + continue; + } + + if (state.key[0] == 'n') { + int index = stoi(state.key.substr(1)); + pixels_shown[index].r = ((uint32_t) state.value >> 16) & 0xff; + pixels_shown[index].g = ((uint32_t) state.value >> 8) & 0xff; + pixels_shown[index].b = state.value & 0xff; + int rc = led_strip_update_rgb(strip, pixels_shown, strip_length); + if (rc) { + printf("couldn't update strip: %d", rc); + } + } + } +} + def_prim(set_pixel_color, fourToOneU32) { uint8_t blue = arg0.uint32; uint8_t green = arg1.uint32; @@ -290,7 +321,7 @@ def_prim(set_pixel_color, fourToOneU32) { def_prim_serialize(set_pixel_color) { for (int i = 0; i < strip_length; i++) { auto *state = new IOStateElement(); - state->key = "n" + std::to_string(i); + state->key = "b" + std::to_string(i); state->output = true; state->value = pixels[i].r << 16 | pixels[i].g << 8 | pixels[i].b; external_state.push_back(state); @@ -303,12 +334,11 @@ def_prim_reverse(set_pixel_color) { continue; } - if (state.key[0] == 'n') { + if (state.key[0] == 'b') { int index = stoi(state.key.substr(1)); pixels[index].r = ((uint32_t) state.value >> 16) & 0xff; pixels[index].g = ((uint32_t) state.value >> 8) & 0xff; pixels[index].b = state.value & 0xff; - invoke_primitive(m, "show_pixels"); } } } @@ -326,6 +356,7 @@ void install_primitives() { install_primitive(set_pixel_color); install_primitive_reverse(set_pixel_color); install_primitive(show_pixels); + install_primitive_reverse(show_pixels); } //------------------------------------------------------