Commit e9baec68 authored by Daniel Friesel's avatar Daniel Friesel
Browse files

add rgbfade support

parent a13d7477
Loading
Loading
Loading
Loading
+133 −63
Original line number Diff line number Diff line
@@ -26,6 +26,32 @@

System blinkencat;

#define BIT_WW _BV(PD5)
#define BIT_RED _BV(PB3)
#define BIT_GREEN _BV(PB4)
#define BIT_BLUE _BV(PB2)

#define PWM_RED OCR1A
#define PWM_GREEN OCR1B
#define PWM_BLUE OCR0A

/*
const uint8_t pwmtable[32] PROGMEM = {
	0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 19, 23,
	27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 255
};
*/

uint8_t const hsbtable[80] PROGMEM = {
	254, 254, 253, 252, 250, 248, 245, 242, 238, 234, 229, 224, 219, 213, 207,
	201, 194, 188, 181, 174, 167, 160, 153, 146, 139, 133, 126, 119, 113, 106,
	100, 94, 88, 83, 78, 72, 67, 63, 58, 54, 50, 46, 43, 39, 36, 33, 30, 28, 25,
	23, 21, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 2, 2, 2,
	1, 1, 1, 1, 0, 0, 0, 0, 0
};

#define HSBTABLE_LEN 80

void System::initialize()
{

@@ -70,76 +96,105 @@ void System::sleep()
	MCUCR &= ~_BV(SE);
}

void System::set_outputs()
void System::loop()
{
	if (warmwhite) {
		PORTD |= _BV(PD5);
	} else {
		PORTD &= ~_BV(PD5);
	}
	if (red) {
		PORTB |= _BV(PB3);
	} else {
		PORTB &= ~_BV(PB3);
	}
	if (green) {
		PORTB |= _BV(PB4);
	} else {
		PORTB &= ~_BV(PB4);
	}
	if (blue) {
		PORTB |= _BV(PB2);
	uint8_t anim_step = 0;
	if (mode_changed) {
		mode_changed = 0;
		if (mode == FASTRGB || mode == SLOWRGB) {
			PORTD &= ~BIT_WW;
			PORTB = 0;
			// 8 bit fast PWM on OC0A, OC1A, OC1B
			TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
			TCCR0B = _BV(CS00);
			TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10);
			TCCR1B = _BV(WGM12) | _BV(CS00);

			// interrupt on Timer 0 overflow
			TIMSK = _BV(TOIE0);
		} else {
		PORTB &= ~_BV(PB2);
			TCCR0A = 0;
			TCCR0B = 0;
			TCCR1A = 0;
			TCCR1B = 0;
			TIMSK = 0;
		}
}

void System::loop()
{
		switch (mode) {
			case OFF:
			warmwhite = red = green = blue = 0;
				PORTD &= ~BIT_WW;
				PORTB = 0;
				break;
			case WARMWHITE:
			warmwhite = 255;
			red = green = blue = 0;
				PORTD |= BIT_WW;
				break;
			case RED:
			red = 255;
			warmwhite = green = blue = 0;
				PORTD &= ~BIT_WW;
				PORTB = BIT_RED;
				break;
			case GREEN:
			green = 255;
			warmwhite = red = blue = 0;
				PORTB = BIT_GREEN;
				break;
			case BLUE:
			blue = 255;
			warmwhite = red = green = 0;
				PORTB = BIT_BLUE;
				break;
			case YELLOW:
			red = green = 255;
			warmwhite = blue = 0;
				PORTB = BIT_RED | BIT_GREEN;
				break;
			case MAGENTA:
			red = blue = 255;
			warmwhite = green = 0;
				PORTB = BIT_RED | BIT_BLUE;
				break;
			case CYAN:
			green = blue = 255;
			warmwhite = red = 0;
				PORTB = BIT_GREEN | BIT_BLUE;
				break;
			case SUN:
			warmwhite = red = green = blue = 255;
				PORTD |= BIT_WW;
				PORTB = BIT_RED | BIT_GREEN | BIT_BLUE;
				break;
			default:
				break;
		}
	set_outputs();
	}

	if (mode == OFF && !btn_debounce) {
		sleep();
	} else {
	if (mode == FASTRGB) {
		anim_step = anim_step_fine;
	} else if (mode == SLOWRGB) {
		anim_step = anim_step_coarse;
	}

	if (mode == FASTRGB || mode == SLOWRGB) {
		if (anim_step < HSBTABLE_LEN) {
			PWM_RED = pgm_read_byte(&hsbtable[anim_step]);
			PWM_GREEN = pgm_read_byte(&hsbtable[HSBTABLE_LEN - 1 - anim_step]);
			PWM_BLUE = 0;
		}
		else if (anim_step < 2*HSBTABLE_LEN) {
			PWM_RED = 0;
			PWM_GREEN = pgm_read_byte(&hsbtable[anim_step - HSBTABLE_LEN]);
			PWM_BLUE = pgm_read_byte(&hsbtable[2*HSBTABLE_LEN - 1 - anim_step]);
		}
		else if (anim_step < 3*HSBTABLE_LEN) {
			PWM_RED = pgm_read_byte(&hsbtable[3*HSBTABLE_LEN - 1 - anim_step]);
			PWM_GREEN = 0;
			PWM_BLUE = pgm_read_byte(&hsbtable[anim_step - 2*HSBTABLE_LEN]);
		}
		if (OCR0A)
			TCCR0A |= _BV(COM0A1);
		else
			TCCR0A &= ~_BV(COM0A1);
		if (OCR1A)
			TCCR1A |= _BV(COM1A1);
		else
			TCCR1A &= ~_BV(COM1A1);
		if (OCR1B)
			TCCR1A |= _BV(COM1B1);
		else
			TCCR1A &= ~_BV(COM1B1);
	}

	if (mode == FASTRGB || mode == SLOWRGB || btn_debounce) {
		idle();
	} else {
		sleep();
	}
}

@@ -147,6 +202,7 @@ void System::next_mode(void)
{
	if (!btn_debounce) {
		mode = (BCMode)((mode + 1) % MODE_ENUM_MAX);
		mode_changed = 1;
	}
}

@@ -171,6 +227,20 @@ ISR(WDT_OVERFLOW_vect)
	blinkencat.debounce_done();
}

ISR(TIMER0_OVF_vect)
{
	static uint8_t slowdown = 0;
	if (++slowdown == 10) {
		if (++blinkencat.anim_step_fine == 3*HSBTABLE_LEN) {
			blinkencat.anim_step_fine = 0;
			if (++blinkencat.anim_step_coarse == 3*HSBTABLE_LEN) {
				blinkencat.anim_step_coarse = 0;
			}
		}
		slowdown = 0;
	}
}

ISR(PCINT2_vect)
{
	if (!(PIND & _BV(PD2))) {
+6 −3
Original line number Diff line number Diff line
@@ -12,11 +12,12 @@ class System {
		uint8_t red;
		uint8_t green;
		uint8_t blue;

		void set_outputs();
		uint8_t mode_changed;

	public:

		uint8_t anim_step_fine;
		uint8_t anim_step_coarse;
		void initialize(void);

		void loop(void);
@@ -33,6 +34,8 @@ class System {
			MAGENTA,
			CYAN,
			SUN,
			FASTRGB,
			SLOWRGB,
			MODE_ENUM_MAX,
		};

@@ -44,7 +47,7 @@ class System {

		void debounce_start(void);

		System() { btn_debounce = 0; mode = OFF; is_charging = 0; };
		System() { btn_debounce = 0; mode = OFF; is_charging = 0; mode_changed = 0; };
};

extern System blinkencat;