-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathws2812.c
141 lines (125 loc) · 3.19 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
/**
* 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
static inline void put_pixel(uint32_t pixel_grb)
{
pio_sm_put_blocking(pio0, 0, 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(uint len, uint t)
{
for (uint i = 0; i < len; ++i)
{
uint x = (i + (t >> 1)) % 64;
if (x < 10)
put_pixel(urgb_u32(0xff, 0, 0));
else if (x >= 15 && x < 25)
put_pixel(urgb_u32(0, 0xff, 0));
else if (x >= 30 && x < 40)
put_pixel(urgb_u32(0, 0, 0xff));
else
put_pixel(0);
}
}
void pattern_random(uint len, uint t)
{
if (t % 8)
return;
for (uint i = 0; i < len; ++i)
put_pixel(rand());
}
void pattern_sparkle(uint len, uint t)
{
if (t % 8)
return;
for (uint i = 0; i < len; ++i)
put_pixel(rand() % 16 ? 0 : 0xffffffff);
}
void pattern_greys(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(t * 0x10101);
if (++t >= max)
t = 0;
}
}
typedef void (*pattern)(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", WS2812_PIN);
// todo get free sm
PIO pio = pio0;
int sm = 0;
uint offset = pio_add_program(pio, &ws2812_program);
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(NUM_PIXELS, t);
sleep_ms(10);
t += dir;
}
}
}