130 lines
3.2 KiB
C
130 lines
3.2 KiB
C
/**
|
|
* 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 (int i = 0; i < len; ++i)
|
|
put_pixel(rand());
|
|
}
|
|
|
|
void pattern_sparkle(uint len, uint t) {
|
|
if (t % 8)
|
|
return;
|
|
for (int i = 0; i < len; ++i)
|
|
put_pixel(rand() % 16 ? 0 : 0xffffffff);
|
|
}
|
|
|
|
void pattern_greys(uint len, uint t) {
|
|
int max = 100; // let's not draw too much current!
|
|
t %= max;
|
|
for (int 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;
|
|
}
|
|
}
|
|
}
|