summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2019-12-17 23:59:05 -0800
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2019-12-17 23:59:05 -0800
commit63966da14ab66bf711547f94e4d185f2027ad253 (patch)
treefddaf4558fb2ed23952768ad549f9dff36422e53
parentc5047bb9952655dc8d0fabf6a54b9e278b243d8b (diff)
downloadchristmas_lights-63966da14ab66bf711547f94e4d185f2027ad253.tar.gz
christmas_lights-63966da14ab66bf711547f94e4d185f2027ad253.tar.xz
add sound-reactive mode and pattern-cycling interrupt
-rw-r--r--config.h20
-rw-r--r--eq.c51
-rw-r--r--eq.h4
-rw-r--r--led.c20
-rw-r--r--led.h6
-rw-r--r--main.c102
6 files changed, 175 insertions, 28 deletions
diff --git a/config.h b/config.h
index 1d25abc..00816db 100644
--- a/config.h
+++ b/config.h
@@ -1,2 +1,18 @@
-#define PIN_LED PB0
-#define NUM_LEDS 50
+#define F_CPU 8000000UL
+
+#define LED_COUNT 50
+#define LED_PIN PB3
+
+#define EQ_PIN_INPUT PB2
+#define EQ_PIN_RESET PB0
+#define EQ_PIN_STROBE PB1
+#define EQ_THRESHOLDS \
+ {16, 82}, \
+ {24, 130}, \
+ {24, 99}, \
+ {24, 79}, \
+ {24, 77}, \
+ {24, 87}, \
+ {26, 37}
+
+#define ISR_PIN PB4
diff --git a/eq.c b/eq.c
new file mode 100644
index 0000000..eb7febd
--- /dev/null
+++ b/eq.c
@@ -0,0 +1,51 @@
+#include "config.h"
+#include "eq.h"
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+unsigned char eq_levels[7];
+
+static const unsigned char thresholds[][2] = { EQ_THRESHOLDS };
+
+static void reset() {
+ PORTB |= (1 << EQ_PIN_RESET);
+ PORTB &= ~(1 << EQ_PIN_RESET);
+ _delay_us(36);
+}
+
+static void strobe() {
+ PORTB |= (1 << EQ_PIN_STROBE);
+ _delay_us(36);
+ PORTB &= ~(1 << EQ_PIN_STROBE);
+ _delay_us(36);
+}
+
+static unsigned char map_level(unsigned char val, unsigned char min, unsigned char max) {
+ if (val <= min)
+ return 0;
+ else if (val >= max)
+ return 255;
+ else
+ return val * 255 / (max - min);
+}
+
+void eq_read() {
+ reset();
+
+ for (int i = 0; i < 7; ++i) {
+ strobe();
+
+ ADCSRA |= (1 << ADSC);
+ while (ADCSRA & (1 << ADSC));
+ eq_levels[i] = map_level(ADCH, thresholds[i][0], thresholds[i][1]);
+ }
+}
+
+void eq_decay() {
+ reset();
+
+ for (int i = 0; i < 7; ++i) {
+ strobe();
+ }
+}
diff --git a/eq.h b/eq.h
new file mode 100644
index 0000000..2ad7beb
--- /dev/null
+++ b/eq.h
@@ -0,0 +1,4 @@
+extern unsigned char eq_levels[];
+
+void eq_decay();
+void eq_read();
diff --git a/led.c b/led.c
index 5ea9923..8d53dea 100644
--- a/led.c
+++ b/led.c
@@ -3,7 +3,7 @@
#include <avr/io.h>
-void signal_bit_0() {
+static void signal_bit_0() {
asm volatile (
"sbi %0, %1\n\t"
"cbi %0, %1\n\t"
@@ -11,11 +11,11 @@ void signal_bit_0() {
"rjmp .+0\n\t"
"rjmp .+0\n\t"
:
- : "I" (_SFR_IO_ADDR(PORTB)), "I" (PIN_LED)
+ : "I" (_SFR_IO_ADDR(PORTB)), "I" (LED_PIN)
);
}
-void signal_bit_1() {
+static void signal_bit_1() {
asm volatile (
"sbi %0, %1\n\t"
"rjmp .+0\n\t"
@@ -24,11 +24,11 @@ void signal_bit_1() {
"rjmp .+0\n\t"
"nop\n\t"
:
- : "I" (_SFR_IO_ADDR(PORTB)), "I" (PIN_LED)
+ : "I" (_SFR_IO_ADDR(PORTB)), "I" (LED_PIN)
);
}
-void signal_byte(unsigned char byte) {
+static void signal_byte(unsigned char byte) {
for (unsigned char mask = 0x80; mask != 0; mask >>= 1) {
if (byte & mask)
signal_bit_1();
@@ -37,20 +37,20 @@ void signal_byte(unsigned char byte) {
}
}
-void signal_led(struct colour *c) {
+static void signal_led(struct colour *c) {
signal_byte(c->r);
signal_byte(c->g);
signal_byte(c->b);
}
-void signal_led_sequence(int num_leds, struct colour *seq, int num_seq, int width, int start) {
+void led_signal_sequence(int num_leds, struct colour *seq, int num_seq, int col_width, int seq_start) {
for(int i = 0; i < num_leds; ++i) {
- int j, p = i - start;
+ int j, p = i - seq_start;
if (p >= 0)
- j = (p / width % num_seq);
+ j = (p / col_width % num_seq);
else
- j = (num_seq - ((p + 1) / -width % num_seq) - 1);
+ j = (num_seq - ((p + 1) / -col_width % num_seq) - 1);
signal_led(&seq[j]);
}
diff --git a/led.h b/led.h
index 585f297..fd11a87 100644
--- a/led.h
+++ b/led.h
@@ -2,8 +2,4 @@ struct colour {
unsigned char r, g, b;
};
-void signal_bit_0();
-void signal_bit_1();
-void signal_byte(unsigned char);
-void signal_led(struct colour *);
-void signal_led_sequence(int, struct colour *, int, int, int);
+void led_signal_sequence(int, struct colour *, int, int, int);
diff --git a/main.c b/main.c
index d1a466d..06c585e 100644
--- a/main.c
+++ b/main.c
@@ -1,17 +1,37 @@
-#define F_CPU 8000000UL
-
-#include <avr/io.h>
-#include <stdlib.h>
-#include <util/delay.h>
-
#include "config.h"
+#include "eq.h"
#include "led.h"
+#include <avr/eeprom.h>
+#include <avr/interrupt.h>
+#include <stdbool.h>
+#include <string.h>
+#include <util/delay.h>
+
static struct colour seq[6];
+static bool interrupted = false;
-int main() {
- DDRB |= (1 << PIN_LED);
- PORTB &= ~(1 << PIN_LED);
+void red_green() {
+ memset(seq, 0, 2 * sizeof(seq[0]));
+
+ seq[0].r = 255;
+ seq[1].g = 255;
+
+ while (1) {
+ for (int i = 0; i < LED_COUNT; ++i) {
+ if (interrupted == true) {
+ interrupted = false;
+ return;
+ }
+
+ led_signal_sequence(LED_COUNT, seq, 2, 1, i);
+ _delay_ms(200);
+ }
+ }
+}
+
+void rainbow() {
+ memset(seq, 0, 6 * sizeof(seq[0]));
seq[0].r = 255;
seq[1].r = 255;
@@ -24,11 +44,71 @@ int main() {
seq[5].b = 255;
while (1) {
- for (int i = 0; i < NUM_LEDS; ++i) {
- signal_led_sequence(NUM_LEDS, seq, 6, 4, i);
+ for (int i = 0; i < LED_COUNT; ++i) {
+ if (interrupted == true) {
+ interrupted = false;
+ return;
+ }
+
+ led_signal_sequence(LED_COUNT, seq, 6, 4, i);
_delay_ms(100);
}
}
+}
+
+void sound_reactive() {
+ memset(seq, 0, 3 * sizeof(seq[0]));
+
+ while (1) {
+ if (interrupted == true) {
+ interrupted = false;
+ return;
+ }
+
+ eq_read();
+
+ seq[0].r = (eq_levels[0] > eq_levels[1]) ? eq_levels[0] : eq_levels[1];
+ unsigned char t = (eq_levels[2] > eq_levels[3]) ? eq_levels[2] : eq_levels[3];
+ seq[1].g = (t > eq_levels[4]) ? t : eq_levels[4];
+ seq[2].b = (eq_levels[5] > eq_levels[6]) ? eq_levels[5] : eq_levels[6];
+
+ led_signal_sequence(LED_COUNT, seq, 3, 1, 0);
+ for (int i = 0; i < 20; ++i) {
+ eq_decay();
+ }
+ _delay_ms(50);
+ }
+}
+
+
+int main() {
+ DDRB |= (1 << LED_PIN);
+ PORTB &= ~(1 << LED_PIN);
+
+ DDRB |= (1 << EQ_PIN_RESET);
+ PORTB &= ~(1 << EQ_PIN_RESET);
+ DDRB |= (1 << EQ_PIN_STROBE);
+ PORTB |= (1 << EQ_PIN_STROBE);
+ DDRB &= ~(1 << EQ_PIN_INPUT);
+
+ DDRB &= ~(1 << ISR_PIN);
+ GIMSK |= (1 << PCIE);
+ PCMSK |= (1 << PCINT4);
+ sei();
+
+ ADMUX |= (1 << MUX0) | (1 << ADLAR);
+ ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
+
+ while (1) {
+ sound_reactive();
+ red_green();
+ rainbow();
+ }
return 0;
}
+
+ISR(PCINT0_vect) {
+ if (!(PINB & (1 << ISR_PIN)))
+ interrupted = true;
+}