summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2018-05-31 12:34:59 +0200
committerDaniel Friesel <derf@finalrewind.org>2018-05-31 12:34:59 +0200
commite9baec681de52ab505e31a4c413ddd41a2ef9458 (patch)
treedc7148169b8de9a9e998107a397d5c76ef5ac575
parenta13d74779b25dda964d81b36b1ab12863111e8f5 (diff)
add rgbfade support
-rw-r--r--src/system.cc196
-rw-r--r--src/system.h9
2 files changed, 139 insertions, 66 deletions
diff --git a/src/system.cc b/src/system.cc
index 66b3a53..2cfbda9 100644
--- a/src/system.cc
+++ b/src/system.cc
@@ -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);
+ 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 {
+ TCCR0A = 0;
+ TCCR0B = 0;
+ TCCR1A = 0;
+ TCCR1B = 0;
+ TIMSK = 0;
+ }
+ switch (mode) {
+ case OFF:
+ PORTD &= ~BIT_WW;
+ PORTB = 0;
+ break;
+ case WARMWHITE:
+ PORTD |= BIT_WW;
+ break;
+ case RED:
+ PORTD &= ~BIT_WW;
+ PORTB = BIT_RED;
+ break;
+ case GREEN:
+ PORTB = BIT_GREEN;
+ break;
+ case BLUE:
+ PORTB = BIT_BLUE;
+ break;
+ case YELLOW:
+ PORTB = BIT_RED | BIT_GREEN;
+ break;
+ case MAGENTA:
+ PORTB = BIT_RED | BIT_BLUE;
+ break;
+ case CYAN:
+ PORTB = BIT_GREEN | BIT_BLUE;
+ break;
+ case SUN:
+ PORTD |= BIT_WW;
+ PORTB = BIT_RED | BIT_GREEN | BIT_BLUE;
+ break;
+ default:
+ break;
+ }
}
- if (blue) {
- PORTB |= _BV(PB2);
- } else {
- PORTB &= ~_BV(PB2);
+
+ if (mode == FASTRGB) {
+ anim_step = anim_step_fine;
+ } else if (mode == SLOWRGB) {
+ anim_step = anim_step_coarse;
}
-}
-void System::loop()
-{
- switch (mode) {
- case OFF:
- warmwhite = red = green = blue = 0;
- break;
- case WARMWHITE:
- warmwhite = 255;
- red = green = blue = 0;
- break;
- case RED:
- red = 255;
- warmwhite = green = blue = 0;
- break;
- case GREEN:
- green = 255;
- warmwhite = red = blue = 0;
- break;
- case BLUE:
- blue = 255;
- warmwhite = red = green = 0;
- break;
- case YELLOW:
- red = green = 255;
- warmwhite = blue = 0;
- break;
- case MAGENTA:
- red = blue = 255;
- warmwhite = green = 0;
- break;
- case CYAN:
- green = blue = 255;
- warmwhite = red = 0;
- break;
- case SUN:
- warmwhite = red = green = blue = 255;
- break;
- default:
- break;
+ 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);
}
- set_outputs();
- if (mode == OFF && !btn_debounce) {
- sleep();
- } else {
+ 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))) {
diff --git a/src/system.h b/src/system.h
index 35c7172..2e50528 100644
--- a/src/system.h
+++ b/src/system.h
@@ -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;