Skip to content

Commit 9ee030d

Browse files
committed
Add basic neopixel support for Zephyr on the rpi pico
1 parent fbff3da commit 9ee030d

File tree

3 files changed

+153
-10
lines changed

3 files changed

+153
-10
lines changed

platforms/Zephyr/boards/rpi_pico.overlay

+41-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#include "../app.overlay"
2+
#include <zephyr/dt-bindings/led/led.h>
23

34
/ {
5+
aliases {
6+
led-strip = &ws2812;
7+
};
8+
49
zephyr,user {
510
warduino-gpios =
611
<&gpio0 0 0>,
@@ -34,4 +39,39 @@
3439
<&gpio0 28 0>,
3540
<&gpio0 29 0>;
3641
};
37-
};
42+
};
43+
44+
&pio1 {
45+
status = "okay";
46+
47+
/*
48+
* Need to put this on PIO1 as having this on PIO0 causes the GPIO hog to
49+
* not work.
50+
*/
51+
pio-ws2812 {
52+
compatible = "worldsemi,ws2812-rpi_pico-pio";
53+
status = "okay";
54+
pinctrl-0 = <&ws2812_pio1_default>;
55+
pinctrl-names = "default";
56+
bit-waveform = <3>, <3>, <4>;
57+
58+
ws2812: ws2812 {
59+
status = "okay";
60+
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
61+
chain-length = <64>;
62+
color-mapping = <LED_COLOR_ID_GREEN
63+
LED_COLOR_ID_RED
64+
LED_COLOR_ID_BLUE>;
65+
reset-delay = <280>;
66+
frequency = <800000>;
67+
};
68+
};
69+
};
70+
71+
&pinctrl {
72+
ws2812_pio1_default: ws2812_pio1_default {
73+
ws2812 {
74+
pinmux = <PIO1_P12>;
75+
};
76+
};
77+
};

platforms/Zephyr/prj.conf

+4
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,7 @@ CONFIG_CONSOLE_PUTCHAR_BUFSIZE=4096
3030

3131
CONFIG_POSIX_API=y
3232
CONFIG_MAIN_STACK_SIZE=8192
33+
34+
CONFIG_LOG=y
35+
CONFIG_LED_STRIP=y
36+
CONFIG_LED_STRIP_LOG_LEVEL_DBG=n

src/Primitives/zephyr.cpp

+108-9
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#include "../Utils/util.h"
3333
#include "primitives.h"
3434

35-
#define ALL_PRIMITIVES 5
35+
#define ALL_PRIMITIVES 9
3636

3737
// Global index for installing primitives
3838
int prim_index = 0;
@@ -262,6 +262,100 @@ def_prim(print_int, oneToNoneU32) {
262262
return true;
263263
}
264264

265+
#include <zephyr/drivers/led_strip.h>
266+
#define RGB(_r, _g, _b) { .r = (_r), .g = (_g), .b = (_b) }
267+
static const struct device *const strip = DEVICE_DT_GET(DT_ALIAS(led_strip));
268+
const size_t strip_length = 64;//led_strip_length(device);
269+
struct led_rgb pixels[strip_length] = {0};
270+
271+
void fun() {
272+
size_t color = 0;
273+
int rc;
274+
275+
if (device_is_ready(strip)) {
276+
printf("Found LED strip device %s\n", strip->name);
277+
} else {
278+
printf("LED strip device %s is not ready\n", strip->name);
279+
return;
280+
}
281+
282+
printf("Displaying pattern on strip\n");
283+
const struct led_rgb colors[] = {
284+
RGB(16, 0x00, 0x00), // red
285+
RGB(0x00, 16, 0x00), // green
286+
RGB(0x00, 0x00, 16), // blue
287+
};
288+
size_t width = 3;
289+
while (1) {
290+
for (size_t cursor = 0; cursor < ARRAY_SIZE(pixels) - width + 1; cursor++) {
291+
memset(&pixels, 0x00, sizeof(pixels));
292+
for (size_t i = 0; i < width; i++) {
293+
memcpy(&pixels[cursor + i], &colors[color], sizeof(struct led_rgb));
294+
color = (color + 1) % ARRAY_SIZE(colors);
295+
}
296+
297+
printf("Update strip!\n");
298+
rc = led_strip_update_rgb(strip, pixels, strip_length);
299+
if (rc) {
300+
printf("couldn't update strip: %d", rc);
301+
}
302+
303+
k_sleep(K_MSEC(100));
304+
}
305+
}
306+
}
307+
308+
def_prim(led_fun, NoneToNoneU32) {
309+
fun();
310+
return true;
311+
}
312+
313+
def_prim(show_pixels, NoneToNoneU32) {
314+
int rc = led_strip_update_rgb(strip, pixels, strip_length);
315+
if (rc) {
316+
printf("couldn't update strip: %d", rc);
317+
}
318+
return true;
319+
}
320+
321+
def_prim(set_pixel_color, fourToOneU32) {
322+
uint8_t blue = arg0.uint32;
323+
uint8_t green = arg1.uint32;
324+
uint8_t red = arg2.uint32;
325+
uint8_t index = arg3.uint32;
326+
327+
led_rgb color = {.r = red, .g = green, .b= blue};
328+
memcpy(&pixels[index], &color, sizeof(struct led_rgb));
329+
pop_args(4);
330+
return true;
331+
}
332+
333+
def_prim_serialize(set_pixel_color) {
334+
for (int i = 0; i < strip_length; i++) {
335+
auto *state = new IOStateElement();
336+
state->key = "n" + std::to_string(i);
337+
state->output = true;
338+
state->value = pixels[i].r << 16 | pixels[i].g << 8 | pixels[i].b;
339+
external_state.push_back(state);
340+
}
341+
}
342+
343+
def_prim_reverse(set_pixel_color) {
344+
for (IOStateElement state : external_state) {
345+
if (!state.output) {
346+
continue;
347+
}
348+
349+
if (state.key[0] == 'n') {
350+
int index = stoi(state.key.substr(1));
351+
pixels[index].r = ((uint32_t) state.value >> 16) & 0xff;
352+
pixels[index].g = ((uint32_t) state.value >> 8) & 0xff;
353+
pixels[index].b = state.value & 0xff;
354+
invoke_primitive(m, "show_pixels");
355+
}
356+
}
357+
}
358+
265359
//------------------------------------------------------
266360
// Installing all the primitives
267361
//------------------------------------------------------
@@ -272,6 +366,10 @@ void install_primitives() {
272366
install_primitive(chip_digital_write);
273367
install_primitive(chip_digital_read);
274368
install_primitive(print_int);
369+
install_primitive(led_fun);
370+
install_primitive(set_pixel_color);
371+
install_primitive_reverse(set_pixel_color);
372+
install_primitive(show_pixels);
275373
}
276374

277375
//------------------------------------------------------
@@ -322,22 +420,23 @@ void restore_external_state(Module *m,
322420
// instructions such as call_indirect
323421
// maybe there should just be a function that checks if a certain function
324422
// is being called that handles all these cases?
325-
if (opcode == 0x10) { // call opcode
423+
/*if (opcode == 0x10) { // call opcode
326424
uint8_t *pc_copy = m->pc_ptr + 1;
327425
uint32_t fidx = read_LEB_32(&pc_copy);
328-
if (fidx < m->import_count) {
329-
for (auto &primitive : primitives) {
330-
if (!strcmp(primitive.name, m->functions[fidx].import_field)) {
426+
if (fidx < m->import_count) {*/
427+
for (int i = 0; i < ALL_PRIMITIVES; i++) {
428+
auto primitive = primitives[i];
429+
printf("%s\n", primitive.name);
430+
//if (!strcmp(primitive.name, m->functions[fidx].import_field)) {
331431
if (primitive.f_reverse) {
332432
debug("Reversing action for primitive %s\n",
333433
primitive.name);
334434
primitive.f_reverse(m, external_state);
335435
}
336-
return;
337-
}
436+
//}
338437
}
339-
}
340-
}
438+
/*}
439+
}*/
341440
}
342441

343442
std::vector<IOStateElement *> get_io_state(Module *m) {

0 commit comments

Comments
 (0)