
// ****************************************************************************
//
//                                 Main code
//
// ****************************************************************************
// Example of driving WS2812 addressable RGB LEDs.

#include "include.h"

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);
}

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"},
};

// output PIO pin
const int PIN_TX = 6;

int main()
{
	//set_sys_clock_48();
	stdio_init_all();
	puts("WS2812 Smoke Test");

	// todo get free sm
	PIO pio = pio0;
	int sm = 0;
	uint offset = pio_add_program(pio, &ws2812_program);

	ws2812_program_init(pio, sm, offset, PIN_TX, 800000, true);

	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(150, t);
			sleep_ms(10);
			t += dir;
		}
	}
}
