123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- #include "Arduino.h"
- #include "Adafruit_NeoPixel.h"
- #include "BackgroundRingClass.h"
- #include "WS2812_Definitions.h"
- BackgroundRingClass::BackgroundRingClass(int led_count, int pin) : Adafruit_NeoPixel(led_count+1, pin, NEO_GRB + NEO_KHZ800) {
- this->led_count = led_count;
- this->action = Idle;
- this->begin();
- }
- void BackgroundRingClass::tick() {
- switch(this->action) {
- case Idle: this->tick_idle(); break;
- case Solid: this->tick_solid(); break;
- case Pulse: this->tick_pulse(); break;
- case PulseAndBeep: this->tick_pulse_and_beep(); break;
- case Spin: this->tick_spin(); break;
- case Flip: this->tick_flip(); break;
- case Slowroll: this->tick_slowroll(); break;
- default: this->action = Idle;
- }
- }
- /* Ring Functions */
- void BackgroundRingClass::setColor(unsigned long color, uint8_t brightness, bool show) {
- this->setBrightness(brightness);
- for(int i=0; i < this->led_count; i++) {
- this->setPixelColor(i, color);
- }
- if(show) {
- this->show();
- }
- }
- void BackgroundRingClass::setRepeating(unsigned long* colors, int elements, int rotation) {
- this->setBrightness(50);
- int curcolor = 0;
- for(int i = 0; i < this->led_count; i++) {
- this->setPixelColor(i, colors[(i+rotation) % elements]);
- }
- this->show();
- }
- ///////////////////////// Idle
- void BackgroundRingClass::init_idle() {
- this->action = Idle;
- this->setColor(BLACK, 255, true);
- }
- void BackgroundRingClass::tick_idle() {
- // noop. Here for consistency
- }
- ///////////////////////// Random
- int BackgroundRingClass::random_event(int copy) {
- int draw = random(0, 480); // this lets us choose events with weighted probability
- if(copy >= 0) { // we wish to copy the other one's action
- draw = copy;
- }
- // Christmas Colors
- if(draw < 50) this->init_pulse(DARKRED, 80, 2000);
- else if(draw < 100) this->init_pulse(DARKGREEN, 80, 2000);
- else if(draw < 150) this->init_spin(DARKRED, DARKGREEN);
- else if(draw < 200) this->init_spin(DARKGREEN, DARKRED);
- else if(draw < 250) this->init_flip(DARKRED, DARKGREEN);
- else if(draw < 300) this->init_flip(DARKGREEN, DARKRED);
- else if(draw < 350) this->init_slowroll(DARKRED, DARKGREEN);
- else if(draw < 400) this->init_slowroll(DARKGREEN, DARKRED);
- // random colors
- else if(draw < 410) this->init_pulse(random(0, 0xFFFFFF), 80, 2000);
- else if(draw < 420) this->init_pulse(random(0, 0xFFFFFF), 80, 2000);
- else if(draw < 430) this->init_spin(random(0, 0xFFFFFF), random(0, 0xFFFFFF));
- else if(draw < 440) this->init_spin(random(0, 0xFFFFFF), random(0, 0xFFFFFF));
- else if(draw < 450) this->init_flip(random(0, 0xFFFFFF), random(0, 0xFFFFFF));
- else if(draw < 460) this->init_flip(random(0, 0xFFFFFF), random(0, 0xFFFFFF));
- else if(draw < 470) this->init_slowroll(random(0, 0xFFFFFF), random(0, 0xFFFFFF));
- else if(draw < 480) this->init_slowroll(random(0, 0xFFFFFF), random(0, 0xFFFFFF));
- return draw;
- }
- ///////////////////////// Solid
- void BackgroundRingClass::init_solid(unsigned long color, uint8_t brightness) {
- this->action = Solid;
- this->setBrightness(brightness);
- this->setColor(color);
- this->show();
- }
- void BackgroundRingClass::tick_solid() {
- // noop. Here for consistency
- }
- ///////////////////////// Pulse
- void BackgroundRingClass::init_pulse(unsigned long color, uint8_t maxbrightness, unsigned long ms) {
- Serial.println("Initializing pulse");
- this->action = Pulse;
- this->pulseinfo.color = color;
- this->pulseinfo.maxbrightness = maxbrightness;
- this->pulseinfo.ms = ms * 1000;
- this->pulseinfo.starttime = micros();
- this->pulseinfo.curbrightness = 1;
- this->pulseinfo.steptime = (ms * 1000) / (2 * (unsigned long)maxbrightness);
- this->setColor(this->pulseinfo.color, this->pulseinfo.curbrightness, true); // dimmest setting
- }
- void BackgroundRingClass::tick_pulse() {
- unsigned long elapsed = micros() - this->pulseinfo.starttime;
- int newbrightness;
- if(elapsed < this->pulseinfo.ms/2) {
- // increasing
- newbrightness = (elapsed / this->pulseinfo.steptime) + 1;
- //Serial.print("Increasing. elapsed="); Serial.print(elapsed);
- //Serial.print("; steptime="); Serial.print(this->pulseinfo.steptime);
- //Serial.print("; curbrightness="); Serial.print(this->pulseinfo.curbrightness);
- //Serial.print("; newbrightenss="); Serial.println(newbrightness);
- } else if(elapsed < this->pulseinfo.ms) {
- // decreasing
- newbrightness = ((this->pulseinfo.ms - elapsed) / this->pulseinfo.steptime) + 1;
- //Serial.print("Decreasing. elapsed="); Serial.print(elapsed);
- //Serial.print("; steptime="); Serial.print(this->pulseinfo.steptime);
- //Serial.print("; curbrightness="); Serial.print(this->pulseinfo.curbrightness);
- //Serial.print("; newbrightenss="); Serial.println(newbrightness);
- } else {
- // done
- //Serial.print("DONE. elapsed="); Serial.print(elapsed);
- this->init_idle();
- return;
- }
- if(newbrightness != this->pulseinfo.curbrightness) {
- this->pulseinfo.curbrightness = newbrightness;
- this->setColor(this->pulseinfo.color, this->pulseinfo.curbrightness, true);
- this->show();
- }
- return;
- }
- ///////////////////////// Pulse and Beep
- //
- // We can't call show() while beeping because it disabled interrupts,
- // so we beep at the peak of the pulse.
- //
- void BackgroundRingClass::init_pulse_and_beep(
- unsigned long color,
- uint8_t maxbrightness,
- unsigned long ms,
- int pin,
- unsigned int frequency,
- unsigned long duration
- ) {
- Serial.println("Initializing pulse and beep");
- this->action = PulseAndBeep;
- this->pulseinfo.color = color;
- this->pulseinfo.maxbrightness = maxbrightness;
- this->pulseinfo.ms = ms * 1000;
- this->pulseinfo.starttime = micros();
- this->pulseinfo.curbrightness = 1;
- this->pulseinfo.steptime = ( (ms - duration) * 1000) / ((2 * (unsigned long)maxbrightness) - 1);
- this->beepinfo.pin = pin;
- this->beepinfo.frequency = frequency;
- this->beepinfo.duration = duration;
- this->beepinfo.state = Beeping;
- this->setColor(this->pulseinfo.color, this->pulseinfo.curbrightness, true); // dimmest setting
- }
- void BackgroundRingClass::tick_pulse_and_beep() {
- // What we're doing should be based on time.
- // Increasing: 0 to (ms - duration)/2))
- // Beeping: (ms - duration)/2 to (ms - duration/2)+duration
- // Decreasing: (ms - duration/2)+duration - ms
- unsigned long elapsed = micros() - this->pulseinfo.starttime;
- int newbrightness;
- if(elapsed < (this->pulseinfo.ms/2 - 1000*this->beepinfo.duration/2)) {
- // increasing
- this->beepinfo.state = Increasing;
- newbrightness = (elapsed / this->pulseinfo.steptime) + 1;
- //Serial.print("Increasing. elapsed="); Serial.print(elapsed);
- //Serial.print("; ms="); Serial.print(this->pulseinfo.ms);
- //Serial.print("; duration="); Serial.print(this->beepinfo.duration);
- //Serial.print("; steptime="); Serial.print(this->pulseinfo.steptime);
- //Serial.print("; curbrightness="); Serial.print(this->pulseinfo.curbrightness);
- //Serial.print("; newbrightenss="); Serial.println(newbrightness);
- } else if(elapsed < (this->pulseinfo.ms/2 + 1000*this->beepinfo.duration/2)) {
- if(this->beepinfo.state != Beeping && this->beepinfo.frequency != 0) {
- tone(this->beepinfo.pin, this->beepinfo.frequency, this->beepinfo.duration);
- this->beepinfo.state = Beeping;
- }
- //Serial.print("Beeping. elapsed="); Serial.print(elapsed);
- //Serial.print("; steptime="); Serial.print(this->pulseinfo.steptime);
- //Serial.print("; curbrightness="); Serial.println(this->pulseinfo.curbrightness);
- return;
- } else if(elapsed < this->pulseinfo.ms) {
- // decreasing
- this->beepinfo.state = Decreasing;
- //newbrightness = ((this->pulseinfo.ms - this->beepinfo.duration/2) / this->pulseinfo.steptime) + 1;
- newbrightness = ((this->pulseinfo.ms - elapsed) / this->pulseinfo.steptime) + 1;
- //Serial.print("Decreasing. elapsed="); Serial.print(elapsed);
- //Serial.print("; ms="); Serial.print(this->pulseinfo.ms);
- //Serial.print("; duration="); Serial.print(this->beepinfo.duration);
- //Serial.print("; steptime="); Serial.print(this->pulseinfo.steptime);
- //Serial.print("; curbrightness="); Serial.print(this->pulseinfo.curbrightness);
- //Serial.print("; newbrightenss="); Serial.println(newbrightness);
- } else {
- // done
- //Serial.print("DONE. elapsed="); Serial.print(elapsed);
- this->init_idle();
- return;
- }
- if(newbrightness != this->pulseinfo.curbrightness) {
- this->pulseinfo.curbrightness = newbrightness;
- this->setColor(this->pulseinfo.color, this->pulseinfo.curbrightness, true);
- this->show();
- }
- return;
- }
- /*
- void BackgroundRingClass::tick_pulse_and_beep() {
- int stepspassed = 0;
- if(this->beepinfo.state == Beeping && (micros() - this->beepinfo.beepstart < 1000*this->beepinfo.duration)) {
- return;
- } else if(this->beepinfo.state == Beeping) {
- Serial.print("Beep Duration was: "); Serial.println((micros() - this->beepinfo.beepstart)/1000);
- Serial.print("Stopping beeping at t="); Serial.println((micros() - this->beepinfo.truestart)/1000);
- this->beepinfo.state = Decreasing;
- this->pulseinfo.starttime = micros() + this->pulseinfo.steptime;
- }
- if((micros() - this->pulseinfo.starttime) < this->pulseinfo.steptime) {
- return;
- } else {
- stepspassed = (micros() - this->pulseinfo.starttime)/this->pulseinfo.steptime;
- }
- //Serial.print("Taking action at t="); Serial.print(micros() - this->beepinfo.truestart);
- //Serial.print("; brightness="); Serial.print(this->pulseinfo.curbrightness);
- //Serial.print("; Steps to take="); Serial.println(stepspassed);
- this->pulseinfo.starttime = micros();
- if(this->beepinfo.state == Increasing && this->pulseinfo.curbrightness == this->pulseinfo.maxbrightness) {
- this->beepinfo.state = Beeping;
- this->beepinfo.beepstart = micros();
- if(this->beepinfo.frequency != 0) {
- Serial.print("Beginning beeping at t="); Serial.println((micros() - this->beepinfo.truestart)/1000);
- tone(this->beepinfo.pin, this->beepinfo.frequency, this->beepinfo.duration);
- return;
- }
- }
- if(this->beepinfo.state == Increasing) {
- if(this->pulseinfo.curbrightness < this->pulseinfo.maxbrightness - stepspassed) {
- this->pulseinfo.curbrightness += stepspassed;
- } else {
- this->pulseinfo.curbrightness = this->pulseinfo.maxbrightness;
- }
- } else {
- if(this->pulseinfo.curbrightness > stepspassed) {
- this->pulseinfo.curbrightness -= stepspassed;
- } else {
- this->pulseinfo.curbrightness = 0;
- }
- }
- if(this->pulseinfo.curbrightness == 0) {
- // We are done
- Serial.print("Stopping pulse at t="); Serial.println((micros() - this->beepinfo.truestart)/1000);
- this->init_idle();
- } else {
- //Serial.print("Setting Brightness: "); Serial.println(this->pulseinfo.curbrightness);
- this->setColor(this->pulseinfo.color, this->pulseinfo.curbrightness, true);
- this->show();
- }
- }
- */
- ///////////////////////// Spin
- void BackgroundRingClass::init_spin(unsigned long color1, unsigned long color2, unsigned long ms, unsigned long tickdelay) {
- this->action = Spin;
- this->spininfo.color1 = color1;
- this->spininfo.color2 = color2;
- this->spininfo.ms = ms * 1000;
- this->spininfo.tickdelay = tickdelay * 1000;
- this->spininfo.starttime = micros();
- this->spininfo.lasttick = micros() - this->spininfo.tickdelay;
- this->spininfo.rotation = 0;
- }
- void BackgroundRingClass::tick_spin() {
- if(micros() - this->spininfo.starttime > this->spininfo.ms) {
- // we're done
- Serial.println(micros() - this->spininfo.starttime);
- this->init_idle();
- return;
- }
- if(micros() - this->spininfo.lasttick > this->spininfo.tickdelay) {
- // Time to spin
- this->spininfo.lasttick = micros();
- this->spininfo.rotation = (this->spininfo.rotation + 1) % 3;
- //unsigned long tickcolors[] = { this->spininfo.color1, this->spininfo.color1, this->spininfo.color1, this->spininfo.color2 };
- //unsigned long tickcolors[] = { BLACK, this->spininfo.color1, this->spininfo.color2 };
- unsigned long tickcolors[] = { BLACK, this->spininfo.color1, this->spininfo.color1, this->spininfo.color2 };
- this->setRepeating(tickcolors, 4, this->spininfo.rotation);
- }
- }
- ///////////////////////// Flip
- void BackgroundRingClass::init_flip(unsigned long color1, unsigned long color2, unsigned long ms, unsigned long tickdelay) {
- this->action = Flip;
- this->flipinfo.color1 = color1;
- this->flipinfo.color2 = color2;
- this->flipinfo.ms = ms * 1000;
- this->flipinfo.tickdelay = tickdelay * 1000;
- this->flipinfo.starttime = micros();
- this->flipinfo.lasttick = micros() - this->flipinfo.tickdelay;
- this->flipinfo.flipper = false;
- }
- void BackgroundRingClass::tick_flip() {
- if(micros() - this->flipinfo.starttime > this->flipinfo.ms) {
- // we're done
- Serial.println(micros() - this->flipinfo.starttime);
- this->init_idle();
- return;
- }
- if(micros() - this->flipinfo.lasttick > this->flipinfo.tickdelay) {
- // Time to flip
- this->flipinfo.lasttick = micros();
- unsigned long tickcolors[] = { this->flipinfo.color1, this->flipinfo.color2 };
- this->setRepeating(tickcolors, 2, (this->flipinfo.flipper ? 0 : 1));
- this->flipinfo.flipper = not(this->flipinfo.flipper);
- }
- }
- ///////////////////////// Slowroll
- void BackgroundRingClass::init_slowroll(unsigned long color1, unsigned long color2, unsigned long ms, unsigned long tickdelay) {
- this->action = Slowroll;
- this->slowrollinfo.color1 = color1;
- this->slowrollinfo.color2 = color2;
- this->slowrollinfo.ms = ms * 1000;
- this->slowrollinfo.tickdelay = tickdelay * 1000;
- this->slowrollinfo.starttime = micros();
- this->slowrollinfo.lasttick = micros() - this->slowrollinfo.tickdelay;
- this->slowrollinfo.flipper = false;
- }
- void BackgroundRingClass::tick_slowroll() {
- if(micros() - this->slowrollinfo.starttime > this->slowrollinfo.ms) {
- // we're done
- Serial.println(micros() - this->slowrollinfo.starttime);
- this->init_idle();
- return;
- }
- if(micros() - this->slowrollinfo.lasttick > this->slowrollinfo.tickdelay) {
- // Time to slowroll
- this->slowrollinfo.lasttick = micros();
- unsigned long tickcolors[] = { this->slowrollinfo.color1, this->slowrollinfo.color2, BLACK };
- this->setRepeating(tickcolors, 3, (this->slowrollinfo.flipper ? 0 : 2));
- this->slowrollinfo.flipper = not(this->slowrollinfo.flipper);
- }
- }
|