Commit 5013d759 authored by Jan Kasprzak's avatar Jan Kasprzak
Browse files

rgb-led-string: christmas tree mode

parent 946b1461
......@@ -4,86 +4,290 @@
#include "rgbstring.h"
unsigned char jiffies;
static unsigned char jiffies;
typedef struct {
unsigned char type : 4;
unsigned char order : 4;
} pixel_t;
// #define CHRISTMAS_TREE 1
pixel_t pixels[STRIP_SIZE];
#define rgb_return(r, g, b) do { send_rgb((r), (g), (b)); return 1; } while(0)
#define VERT_SIZE 47
/* RNG from ADC noise */
static unsigned char rand_pool[8], rand_pool_off, prev_bit, rand_pool_out;
static void init_rng()
{
ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1); // enable, clk/64
ADMUX = _BV(REFS1) | _BV(MUX0) | _BV(MUX3); // 1.1V, PB5:PB5, gain 20
DIDR0 = _BV(ADC0D);
ADCSRA |= _BV(ADIE) | _BV(ADSC);
rand_pool_off = 0;
prev_bit = 0;
}
static unsigned char rand() {
unsigned char rv = 0;
rv = rand_pool[rand_pool_out];
rand_pool_out++;
if (rand_pool_out >= sizeof(rand_pool))
rand_pool_out = 0;
return rv;
}
ISR(ADC_vect) {
ADCSRA |= _BV(ADSC);
if ((rand_pool_off & 1) == 0) { // first bit of the pair
prev_bit = ADCW & 1;
rand_pool_off++;
} else {
unsigned char bit = ADCW & 1;
if (bit == prev_bit) { // whitening fail: try again
rand_pool_off--;
return;
}
if (bit) {
rand_pool[rand_pool_off >> 4]
^= 1 << ((rand_pool_off >> 1) & 7);
}
rand_pool_off++;
if (rand_pool_off >= 16*sizeof(rand_pool))
rand_pool_off = 0;
}
}
/* up and down running stars at the beginning/end of the strip */
static unsigned char updown_star, updown_star0, updown_down, updown_bright;
static void updown_star_init()
{
updown_star0 = 0;
updown_down = 1;
}
static void updown_star_frame()
{
if (updown_star0 == 0) {
updown_star0 = STRIP_SIZE-VERT_SIZE-8;
updown_down = 0;
} else if (updown_star0 == STRIP_SIZE + 8) {
updown_star0 = VERT_SIZE+7;
updown_down = 1;
} else if (updown_star0 <= VERT_SIZE + 8) {
updown_star0--;
} else if (updown_star0 >= STRIP_SIZE-VERT_SIZE-8) {
updown_star0++;
}
if (updown_down && updown_star0 < 8) {
updown_star = 0;
updown_bright = 1 << updown_star0;
} else if (updown_down) {
updown_star = updown_star0 - 8;
updown_bright = 128;
} else if (updown_star0 < STRIP_SIZE-VERT_SIZE) {
updown_star = STRIP_SIZE-VERT_SIZE;
updown_bright = 1 << (STRIP_SIZE-VERT_SIZE-updown_star0);
} else {
updown_star = updown_star0;
updown_bright = 1;
}
}
static unsigned char updown_star_pixel(unsigned char pos)
{
if (pos >= VERT_SIZE && pos < STRIP_SIZE-VERT_SIZE)
return 0;
if (pos == updown_star) {
send_rgb(updown_bright, updown_bright, updown_bright);
if (updown_down) {
updown_bright >>= 1;
if (updown_bright)
updown_star++;
} else {
updown_bright <<= 1;
if (updown_bright)
updown_star++;
}
return 1;
}
return 0;
}
/* down running stars at the beginning/end of the strip */
static unsigned char down_star, down_star0, down_bright;
static void down_star_init()
{
down_star0 = STRIP_SIZE;
}
static void down_star_frame()
{
if (down_star0 == 0) {
down_star0 = STRIP_SIZE;
} else {
down_star0--;
}
if (down_star0 < 8) {
down_star = 0;
down_bright = 1 << down_star0;
} else {
down_star = down_star0;
down_bright = 128;
}
}
static unsigned char down_star_pixel(unsigned char pos)
{
if (pos == down_star) {
send_rgb(down_bright, down_bright, down_bright);
down_bright >>= 1;
if (down_bright)
down_star++;
return 1;
}
return 0;
}
/* middle stars */
static unsigned char midstar_pos0, midstar_pos, midstar_bright, midstar_color;
static void midstar_init()
{
midstar_pos0 = STRIP_SIZE/2;
midstar_color = 0;
}
static unsigned int slow_dim[] = {
255, 182, 130, 92, 66, 47, 33, 24, 17, 12, 8, 6, 4, 3, 2, 1,
};
static void midstar_frame()
{
unsigned char phase = (jiffies) & 0x1F;
midstar_bright = phase & 0x10 ? slow_dim[phase & 0x0F]
: slow_dim[15-(phase & 0x0F)];
if (!phase) {
unsigned char c = rand();
#ifdef CHRISTMAS_TREE
midstar_pos0 = 2 + (c % (STRIP_SIZE - 4));
#else
midstar_pos0 -= 2 + VERT_SIZE;
midstar_pos0 += 16 + (c & 0x1F);
midstar_pos0 &= 0x3F;
midstar_pos0 += 2 + VERT_SIZE;
#endif
midstar_color += 1 + (c & 0xC0 ? 0 : 1);
}
midstar_pos = midstar_pos0 - 2;
}
static unsigned char midstar_pixel(unsigned char pos)
{
unsigned char dim;
if (pos != midstar_pos)
return 0;
if (pos > midstar_pos0) {
dim = pos - midstar_pos0;
if (dim < 2)
midstar_pos++;
} else {
dim = midstar_pos0 - pos;
midstar_pos++;
}
dim = midstar_bright >> 2*dim;
if (dim >= 2) {
switch (midstar_color & 0x7) {
case 0: send_rgb(dim, 0, 0); break; // red
case 1: send_rgb(dim, dim, dim); break; // white
case 2: send_rgb(0, dim, 0); break; // green
case 3: send_rgb(dim, 0, dim); break; // violet
case 4: send_rgb(dim, dim >> 2, 0); break; // yellow/orange
case 5: send_rgb(0, dim, dim >> 2); break; // cyan
case 6: send_rgb(0, 0, dim); break; // blue
case 7: send_rgb(dim, dim, 0); break; // yellow
}
return 1;
} else {
return 0;
}
}
static void background(unsigned char pos)
{
#ifdef CHRISTMAS_TREE
switch ((pos >> 4) & 3) {
case 0: if (pos & 1) send_rgb(7, 0, 0); else send_rgb(0, 7, 0);
break;
case 1: if (pos & 1) send_rgb(0, 0, 7); else send_rgb(7, 7, 7);
break;
case 2: if (pos & 1) send_rgb(7, 0, 7); else send_rgb(0, 7, 5);
break;
case 3: if (pos & 1) send_rgb(7, 5, 0); else send_rgb(7, 7, 7);
break;
}
#else
send_rgb(0, 0, 7);
#endif
}
int main(void)
{
unsigned char i, start, rgb, jiffies;
init_log();
init_rng();
init_serial();
_delay_ms(3000/8);
_delay_ms(3000/8); // wait for a bit and then increase the CPU clock
CLKPR = _BV(CLKPCE);
CLKPR = 0;
for (i = 0; i < STRIP_SIZE; i+= 23)
pixels[i].type = 2;
sei();
while (1) {
jiffies++;
if ((jiffies & 7) == 0) {
pixels[start].type = 1;
pixels[start].order = 14;
}
#ifdef CHRISTMAS_TREE
down_star_init();
#else
updown_star_init();
#endif
midstar_init();
if ((jiffies & 7) == 3) {
pixels[start].type = 2;
pixels[start].order = 0;
start += 19;
}
while (1) {
unsigned char i;
start += 63;
if (start >= STRIP_SIZE)
start -= STRIP_SIZE;
++jiffies;
#ifdef CHRISTMAS_TREE
down_star_frame();
#else
updown_star_frame();
#endif
midstar_frame();
for (i = 0; i < STRIP_SIZE; i++) {
unsigned char type = pixels[i].type;
unsigned char order = pixels[i].order;
switch (type) {
case 0:
send_rgb(0, 0, 4);
break;
case 1:
case 3:
send_rgb(
6+(1 << (order/2)),
6+(1 << (order/2)),
6+(1 << (order/2))
);
pixels[i].type = type == 3 ? 2 : 0;;
if (order > 1 && i) {
pixels[i-1].type = pixels[i-1].type == 2 ? 3 : 1;
pixels[i-1].order = order-1;
}
break;
case 2:
if (order >= 8) {
send_rgb(1 << ((15-order) / 2), 0, 0);
} else {
send_rgb(1 << (order/2), 0, 0);
}
if (++order >= 15)
pixels[i].type = 0;
pixels[i].order = order;
break;
}
#ifdef CHRISTMAS_TREE
if (down_star_pixel(i)) continue;
#else
if (updown_star_pixel(i)) continue;
#endif
if (midstar_pixel(i)) continue;
background(i);
}
end_frame();
_delay_ms(50);
#if 0
log_byte(0xFa);
log_flush();
#endif
_delay_ms(30);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment