#include <avr/io.h>
#include <stdlib.h> // for NULL

#include "lights.h"

#define N_LEDS 2
static unsigned char bits_left[N_LEDS];
static unsigned char *pattern_data[N_LEDS];
static unsigned char current_bit[N_LEDS];

static unsigned char off_pattern[] = {
	0b00000000,
};

void led_set_pattern(unsigned char led, unsigned char bits_len,
	unsigned char bits_start,
	unsigned char *data)
{
	if (!bits_len) {
		led_set_pattern(led, 8, 0, off_pattern);
	} else {
		bits_left[led] = bits_len-1;
		current_bit[led] = bits_start;
		pattern_data[led] = data;
	}
}

void led_set_number_pattern(unsigned char led, unsigned char num,
	unsigned char inv)
{
	static unsigned char pattern_num[] = {
		0b00100000, /*  10 */
		0b10000010, /* 8,9 */
		0b00001000, /*   7 */
		0b00100000, /*   6 */
		0b10000010, /* 4,5 */
		0b00001000, /*   3 */
		0b00100000, /*   2 */
		0b10000000, /*   1 */
		0b00000000,
	};

	static unsigned char pattern_invnum[] = {
		0b11011111, /*  10 */
		0b01111101, /* 8,9 */
		0b11110111, /*   7 */
		0b11011111, /*   6 */
		0b01111101, /* 4,5 */
		0b11110111, /*   3 */
		0b11011111, /*   2 */
		0b01111111, /*   1 */
		0b11111111,
	};

	unsigned char bits_len, bits_remaining;

	if (num > 10)
		num = 10;

	bits_len = 6*num + 12;
	bits_remaining = 9*8 - bits_len;
	log_byte(0x88);
	log_byte(bits_len);
	log_byte(bits_remaining & 7);
	log_byte(bits_remaining >> 3);
	log_flush();
	led_set_pattern(led, bits_len, bits_remaining & 7,
		inv ? pattern_invnum + (bits_remaining >> 3)
		    : pattern_num    + (bits_remaining >> 3));
}

static void inline pattern_select(unsigned char n)
{
	switch(n) {
	case 0: pwmled_pattern_select(n);
		break;
	case 1: status_led_pattern_select(n);
		break;
	}
}

static void inline led_set_mode(unsigned char n, unsigned char mode)
{
	switch (n) {
	case 0: pwmled_on_off(mode); break;
	case 1: status_led_on_off(mode); log_byte(mode); log_flush(); break;
	}
}

void patterns_next_tick()
{
	unsigned char i;

	for (i = 0; i < N_LEDS; i++) {
		if (!bits_left[i]) {
			pattern_select(i);
		} else {
			bits_left[i]--;
			current_bit[i]++;
			if (current_bit[i] >= 8) {
				current_bit[i] = 0;
				pattern_data[i]++;
			}
		}

		led_set_mode(i, *(pattern_data[i]) & (1 << (7 - current_bit[i]))
			? 1 : 0);
	}
}

void init_pattern()
{
	unsigned char i;

	for (i = 0; i < N_LEDS; i++)
		led_set_pattern(i, 0, 0, NULL);
}

void pattern_reload()
{
	unsigned char i;

	for (i = 0; i < N_LEDS; i++)
		bits_left[i] = 0;

	patterns_next_tick();
}

