-
Notifications
You must be signed in to change notification settings - Fork 878
/
Copy pathws2812.c
143 lines (124 loc) · 4.06 KB
/
ws2812.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/clocks.h"
#include "ws2812.pio.h"
/**
* NOTE:
* Take into consideration if your WS2812 is a RGB or RGBW variant.
*
* If it is RGBW, you need to set IS_RGBW to true and provide 4 bytes per
* pixel (Red, Green, Blue, White) and use urgbw_u32().
*
* If it is RGB, set IS_RGBW to false and provide 3 bytes per pixel (Red,
* Green, Blue) and use urgb_u32().
*
* When RGBW is used with urgb_u32(), the White channel will be ignored (off).
*
*/
#define IS_RGBW false
#define NUM_PIXELS 150
#ifdef PICO_DEFAULT_WS2812_PIN
#define WS2812_PIN PICO_DEFAULT_WS2812_PIN
#else
// default to pin 2 if the board doesn't have a default WS2812 pin defined
#define WS2812_PIN 2
#endif
// Check the pin is compatible with the platform
#if WS2812_PIN >= NUM_BANK0_GPIOS
#error Attempting to use a pin>=32 on a platform that does not support it
#endif
static inline void put_pixel(PIO pio, uint sm, uint32_t pixel_grb) {
pio_sm_put_blocking(pio, sm, pixel_grb << 8u);
}
static inline uint32_t urgb_u32(uint8_t r, uint8_t g, uint8_t b) {
return
((uint32_t) (r) << 8) |
((uint32_t) (g) << 16) |
(uint32_t) (b);
}
static inline uint32_t urgbw_u32(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return
((uint32_t) (r) << 8) |
((uint32_t) (g) << 16) |
((uint32_t) (w) << 24) |
(uint32_t) (b);
}
void pattern_snakes(PIO pio, uint sm, uint len, uint t) {
for (uint i = 0; i < len; ++i) {
uint x = (i + (t >> 1)) % 64;
if (x < 10)
put_pixel(pio, sm, urgb_u32(0xff, 0, 0));
else if (x >= 15 && x < 25)
put_pixel(pio, sm, urgb_u32(0, 0xff, 0));
else if (x >= 30 && x < 40)
put_pixel(pio, sm, urgb_u32(0, 0, 0xff));
else
put_pixel(pio, sm, 0);
}
}
void pattern_random(PIO pio, uint sm, uint len, uint t) {
if (t % 8)
return;
for (uint i = 0; i < len; ++i)
put_pixel(pio, sm, rand());
}
void pattern_sparkle(PIO pio, uint sm, uint len, uint t) {
if (t % 8)
return;
for (uint i = 0; i < len; ++i)
put_pixel(pio, sm, rand() % 16 ? 0 : 0xffffffff);
}
void pattern_greys(PIO pio, uint sm, uint len, uint t) {
uint max = 100; // let's not draw too much current!
t %= max;
for (uint i = 0; i < len; ++i) {
put_pixel(pio, sm, t * 0x10101);
if (++t >= max) t = 0;
}
}
typedef void (*pattern)(PIO pio, uint sm, uint len, uint t);
const struct {
pattern pat;
const char *name;
} pattern_table[] = {
{pattern_snakes, "Snakes!"},
{pattern_random, "Random data"},
{pattern_sparkle, "Sparkles"},
{pattern_greys, "Greys"},
};
int main() {
//set_sys_clock_48();
stdio_init_all();
printf("WS2812 Smoke Test, using pin %d\n", WS2812_PIN);
// todo get free sm
PIO pio;
uint sm;
uint offset;
// This will find a free pio and state machine for our program and load it for us
// We use pio_claim_free_sm_and_add_program_for_gpio_range (for_gpio_range variant)
// so we will get a PIO instance suitable for addressing gpios >= 32 if needed and supported by the hardware
bool success = pio_claim_free_sm_and_add_program_for_gpio_range(&ws2812_program, &pio, &sm, &offset, WS2812_PIN, 1, true);
hard_assert(success);
ws2812_program_init(pio, sm, offset, WS2812_PIN, 800000, IS_RGBW);
int t = 0;
while (1) {
int pat = rand() % count_of(pattern_table);
int dir = (rand() >> 30) & 1 ? 1 : -1;
puts(pattern_table[pat].name);
puts(dir == 1 ? "(forward)" : "(backward)");
for (int i = 0; i < 1000; ++i) {
pattern_table[pat].pat(pio, sm, NUM_PIXELS, t);
sleep_ms(10);
t += dir;
}
}
// This will free resources and unload our program
pio_remove_program_and_unclaim_sm(&ws2812_program, pio, sm, offset);
}