Created
February 10, 2014 23:03
-
-
Save rkbenton/8926010 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
(This is an implementation of the Modified BSD License. This version allows unlimited | |
redistribution for any purpose as long as its copyright notices and the license's | |
disclaimers of warranty are maintained. The license also contains a clause restricting | |
use of the names of contributors for endorsement of a derived work without specific | |
permission.) | |
Copyright (c) 2013-2014, Rebecca K. Benton | |
All rights reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions are met: | |
* Redistributions of source code must retain the above copyright | |
notice, this list of conditions and the following disclaimer. | |
* Redistributions in binary form must reproduce the above copyright | |
notice, this list of conditions and the following disclaimer in the | |
documentation and/or other materials provided with the distribution. | |
* Neither the name of the <organization> nor the | |
names of its contributors may be used to endorse or promote products | |
derived from this software without specific prior written permission. | |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY | |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
/* | |
Notes: | |
o This is a quick-and-dirty program writte to play with Digistump's | |
Digispark USB Development Board (http://digistump.com/products/1) | |
o It can be compiled using Visual Studio (or any other advanced IDE) | |
be including a #define WIN32. If not def'd, it can be compiled in | |
the special Arduino IDE provided by Digistump | |
o This is /not/ an indication of my mode of programming; this was a | |
quick, fun side-project that was for experimentation, not for any | |
sort of long-lived development | |
*/ | |
#include <DigisparkRGB.h> | |
byte RED = 0; | |
byte BLUE = 2; | |
byte GREEN = 1; | |
// == aColor ======================================================== | |
// def | |
struct aColor { | |
byte r; | |
byte g; | |
byte b; | |
aColor(); | |
aColor(byte inR, byte inG, byte inB); | |
void SetValues(byte inR, byte inG, byte inB); | |
}; | |
// impl | |
aColor::aColor() : r(0), g(0), b(0){} | |
aColor::aColor(byte inR, byte inG, byte inB) : r(inR), g(inG), b(inB){} | |
void aColor::SetValues(byte inR, byte inG, byte inB) { | |
r = inR; | |
g = inG; | |
b = inB; | |
} | |
// == ColorScheme ======================================================== | |
#define MAX_SCHEME_COLORS 5 | |
class ColorScheme { | |
public: | |
aColor* colors[MAX_SCHEME_COLORS]; | |
int count; | |
int idx; | |
ColorScheme(); | |
void Add(aColor*); | |
aColor* GetColor(int); | |
aColor GetRandomColor(); | |
int GetCount(); | |
}; | |
ColorScheme::ColorScheme() { | |
count = 0; | |
idx = 0; | |
} | |
aColor ColorScheme::GetRandomColor() { | |
idx = random(this->GetCount()); | |
aColor* c = colors[idx]; | |
return *c; | |
} | |
void ColorScheme::Add(aColor* c) { | |
if (count < (MAX_SCHEME_COLORS - 1)) { | |
colors[count++] = c; | |
} | |
} | |
aColor* ColorScheme::GetColor(int idx) { | |
if (idx < 0) { | |
return colors[0]; // negative idx? be safe and quietly return first color | |
} | |
if (idx > (count - 1) || idx >= MAX_SCHEME_COLORS) { | |
return colors[count - 1]; // if off end of built colors or array itself, return last color | |
} | |
return colors[idx]; // return color requested | |
} | |
int ColorScheme::GetCount() { | |
return count; | |
} | |
enum {Black, White, Grey, LightGray, SlateGray, CornflowerBlue, DeepSkyBlue, DodgerBlue, | |
LightBlue, Cyan, LightCyan, LightSkyBlue, MediumBlue, MediumTurquoise, Aquamarine, | |
MediumAquamarine, RosyBrown, SaddleBrown, SandyBrown, DarkGreen, DarkOliveGreen, chartreuse, | |
DarkOrange, DarkSalmon, LightPink, Pink, AntiqueWhite, Linen, Wheat, BlanchedAlmond, | |
LightGoldenrod, Gold}; | |
aColor colorArray[] = { | |
aColor(0, 0, 0), | |
aColor(255, 255, 255), | |
aColor(84, 84, 84), | |
aColor(211, 211, 211), | |
aColor(112, 128, 144), | |
aColor(100, 149, 237), | |
aColor(0, 191, 255), | |
aColor(30, 144, 255), | |
aColor(170, 187, 204), | |
aColor(0, 255, 255), | |
aColor(224, 255, 255), | |
aColor(135, 206, 250), | |
aColor(0, 0, 205), | |
aColor(72, 209, 204), | |
aColor(127, 255, 212), | |
aColor(102, 205, 170), | |
aColor(188, 143, 143), | |
aColor(139, 69, 19), | |
aColor(244, 164, 96), | |
aColor(47, 79, 47), | |
aColor(85, 107, 47), | |
aColor(127, 255, 0), | |
aColor(255, 140, 0), | |
aColor(233, 150, 122), | |
aColor(255, 182, 193), | |
aColor(255, 192, 203), | |
aColor(250, 235, 215), | |
aColor(250, 240, 230), | |
aColor(245, 222, 179), | |
aColor(255, 235, 205), | |
aColor(238, 221, 130), | |
aColor(255, 215, 0) | |
}; | |
#define MAX_SCHEMES 5 | |
static ColorScheme schemes[MAX_SCHEMES]; | |
void CreatesColorSchemes() { | |
ColorScheme* theScheme = &schemes[0]; | |
theScheme->Add(&colorArray[Grey]); | |
theScheme->Add(&colorArray[LightGray]); | |
theScheme->Add(&colorArray[CornflowerBlue]); | |
theScheme->Add(&colorArray[DarkGreen]); | |
theScheme->Add(&colorArray[DarkOliveGreen]); | |
#ifdef WIN32 | |
printf("scheme1 Added %d colors\n", theScheme->GetCount()); | |
for (int i = 0; i < theScheme->GetCount(); ++i) { | |
aColor* c = theScheme->GetItem(i); | |
printf("\t%d: %u, %u, %u\n", i, c->r, c->g, c->b); | |
} | |
#endif // WIN32 | |
theScheme = &schemes[1]; | |
theScheme->Add(&colorArray[SaddleBrown]); | |
theScheme->Add(&colorArray[SandyBrown]); | |
theScheme->Add(&colorArray[DarkGreen]); | |
theScheme->Add(&colorArray[BlanchedAlmond]); | |
theScheme->Add(&colorArray[Gold]); | |
theScheme->Add(&colorArray[Aquamarine]); | |
#ifdef WIN32 | |
printf("Added %d colors\n", theScheme->GetCount()); | |
for (int i = 0; i < theScheme->GetCount(); ++i) { | |
aColor* c = theScheme->GetItem(i); | |
printf("\t%d: %u, %u, %u\n", i, c->r, c->g, c->b); | |
} | |
#endif // WIN32 | |
theScheme = &schemes[2]; | |
theScheme->Add(&colorArray[CornflowerBlue]); | |
theScheme->Add(&colorArray[MediumBlue]); | |
theScheme->Add(&colorArray[DarkGreen]); | |
theScheme->Add(&colorArray[DarkSalmon]); | |
#ifdef WIN32 | |
printf("Added %d colors\n", theScheme->GetCount()); | |
for (int i = 0; i < theScheme->GetCount(); ++i) { | |
aColor* c = theScheme->GetItem(i); | |
printf("\t%d: %u, %u, %u\n", i, c->r, c->g, c->b); | |
} | |
#endif // WIN32 | |
theScheme = &schemes[3]; | |
theScheme->Add(&colorArray[White]); | |
theScheme->Add(&colorArray[LightCyan]); | |
theScheme->Add(&colorArray[DarkSalmon]); | |
theScheme->Add(&colorArray[MediumBlue]); | |
theScheme->Add(&colorArray[RosyBrown]); | |
theScheme->Add(&colorArray[Wheat]); | |
#ifdef WIN32 | |
printf("Added %d colors\n", theScheme->GetCount()); | |
for (int i = 0; i < theScheme->GetCount(); ++i) { | |
aColor* c = theScheme->GetItem(i); | |
printf("\t%d: %u, %u, %u\n", i, c->r, c->g, c->b); | |
} | |
#endif // WIN32 | |
theScheme = &schemes[4]; | |
theScheme->Add(&colorArray[White]); | |
theScheme->Add(&colorArray[LightCyan]); | |
theScheme->Add(&colorArray[MediumBlue]); | |
theScheme->Add(&colorArray[DarkOliveGreen]); | |
theScheme->Add(&colorArray[SaddleBrown]); | |
theScheme->Add(&colorArray[DarkOrange]); | |
#ifdef WIN32 | |
printf("scheme5 Added %d colors\n", theScheme->GetCount()); | |
for (int i = 0; i < theScheme->GetCount(); ++i) { | |
aColor* c = theScheme->GetItem(i); | |
printf("\t%d: %u, %u, %u\n", i, c->r, c->g, c->b); | |
} | |
#endif // WIN32 | |
} | |
enum showState{ACT, SCENE_START, SCENE_DONE, FADE_OUT_BEGIN, FADE_OUT, FADE_OUT_DONE, COMMERCIAL}; | |
struct StateVars { | |
showState currShowState; | |
unsigned long currStateStarted; | |
unsigned long currStateEndsAt; | |
int currStateEndsAfterNIterations; | |
int jitterIterations; | |
ColorScheme currColorScheme; | |
aColor currSchemeColor; | |
aColor currRenderColor; | |
int numScenesLeftInAct; | |
int jitterR; | |
int jitterG; | |
int jitterB; | |
int FADE_OUT_MS; | |
StateVars() { | |
currShowState = ACT; | |
numScenesLeftInAct = random(5); | |
FADE_OUT_MS = 2000; | |
currStateEndsAfterNIterations = 0; | |
jitterIterations = 0; | |
jitterR = 0; | |
jitterG = 0; | |
jitterB = 0; | |
} | |
byte AddJitter(byte colorVal, int jitter) { | |
int newVal = constrain(colorVal + jitter, 0, 255); // jitter may be negative | |
return (byte)newVal; | |
} | |
}; | |
void setup() { | |
// Serial.begin(9600); // open the serial port at 9600 bps: | |
DigisparkRGBBegin(); | |
randomSeed(analogRead(0)); | |
// schemes | |
CreatesColorSchemes(); | |
} | |
#define DELAY_MS 25 | |
#define ITERATIONS_PER_SECOND (1000 / 25) | |
void loop () | |
{ | |
static StateVars stateVars; | |
/* | |
if (0 >= stateVars.currStateEndsAfterNIterations--) { | |
switch(stateVars.currShowState) { | |
case ACT: | |
stateVars.currSchemeColor.r = 0; stateVars.currSchemeColor.g = 0; stateVars.currSchemeColor.b = 255; | |
stateVars.currShowState = SCENE_START; | |
stateVars.currStateEndsAfterNIterations = 1000 / DELAY_MS; | |
break; | |
case SCENE_START: | |
stateVars.currSchemeColor.r = 0; stateVars.currSchemeColor.g = 255; stateVars.currSchemeColor.b = 0; | |
stateVars.currShowState = ACT; | |
stateVars.currStateEndsAfterNIterations = 500 / DELAY_MS; | |
break; | |
default: | |
stateVars.currSchemeColor.r = 255; stateVars.currSchemeColor.g = 0; stateVars.currSchemeColor.b = 0; | |
} | |
} | |
stateVars.currRenderColor = stateVars.currSchemeColor; | |
DigisparkRGB(RED, stateVars.currRenderColor.r); | |
DigisparkRGB(GREEN, stateVars.currRenderColor.g); | |
DigisparkRGB(BLUE, stateVars.currRenderColor.b); | |
DigisparkRGBDelay(DELAY_MS); | |
return; | |
*/ | |
bool switchAgain = false; | |
do { | |
switchAgain = false; | |
if (0 >= stateVars.currStateEndsAfterNIterations--) { | |
switch(stateVars.currShowState) { | |
case ACT: | |
stateVars.numScenesLeftInAct = random(7, 10); | |
stateVars.currColorScheme = schemes[random(MAX_SCHEMES)]; | |
stateVars.currShowState = SCENE_START; | |
switchAgain = true; | |
break; | |
case SCENE_START: | |
stateVars.currStateEndsAfterNIterations = random(3, 10) * ITERATIONS_PER_SECOND; | |
stateVars.currSchemeColor = stateVars.currColorScheme.GetRandomColor(); | |
stateVars.currShowState = SCENE_DONE; | |
break; | |
case SCENE_DONE: | |
stateVars.numScenesLeftInAct--; | |
if (0 >= stateVars.numScenesLeftInAct) { | |
stateVars.currShowState = FADE_OUT_BEGIN; | |
} else { | |
stateVars.currShowState = SCENE_START; | |
switchAgain = true; | |
} | |
break; | |
case FADE_OUT_BEGIN: | |
stateVars.currStateEndsAfterNIterations = stateVars.FADE_OUT_MS / DELAY_MS; | |
stateVars.currShowState = FADE_OUT; | |
break; | |
case FADE_OUT: | |
stateVars.currShowState = FADE_OUT_DONE; | |
break; | |
case FADE_OUT_DONE: | |
stateVars.currShowState = COMMERCIAL; | |
switchAgain = true; | |
break; | |
case COMMERCIAL: | |
stateVars.currShowState = ACT; | |
#ifdef WIN32 | |
std::cout << "case COMMERCIAL \n" << "press any key to quit"; | |
std::cin.get(); | |
#endif | |
switchAgain = true; | |
break; | |
default: | |
stateVars.currRenderColor.r = 11; stateVars.currRenderColor.g = 11; stateVars.currRenderColor.b = 11; | |
stateVars.currShowState = ACT; | |
switchAgain = true; | |
break; | |
} | |
} | |
} while (switchAgain); | |
stateVars.currRenderColor = stateVars.currSchemeColor; | |
if (stateVars.currShowState == FADE_OUT) { | |
long factor = 20; | |
long denom = stateVars.FADE_OUT_MS / DELAY_MS; | |
long numer = denom - (stateVars.currStateEndsAfterNIterations > 0 ? stateVars.currStateEndsAfterNIterations: 0); | |
stateVars.currRenderColor.r = | |
(byte) (stateVars.currRenderColor.r - ((stateVars.currRenderColor.r * numer * factor) / denom)/factor); | |
stateVars.currRenderColor.g = | |
(byte) (stateVars.currRenderColor.g - ((stateVars.currRenderColor.g * numer * factor) / denom)/factor); | |
stateVars.currRenderColor.b = | |
(byte) (stateVars.currRenderColor.b - ((stateVars.currRenderColor.b * numer * factor) / denom)/factor); | |
// double fadeRatio = 1.0 - ((now - stateVars.currStateStarted) / (double)stateVars.FADE_OUT_MS); | |
// if (fadeRatio < 0) fadeRatio = 0; | |
// stateVars.currRenderColor.r *= fadeRatio; | |
// stateVars.currRenderColor.g *= fadeRatio; | |
// stateVars.currRenderColor.b *= fadeRatio; | |
// printf("\tFaded color to %d, %d, %d\n", stateVars.currRenderColor.r, stateVars.currRenderColor.g, stateVars.currRenderColor.b); | |
} | |
// perhaps add some light jitter | |
if (0 >= stateVars.jitterIterations && random(0,100) < 10) { | |
stateVars.jitterIterations = abs(random(6, 50)); | |
int r = random(0,100); | |
if (r < 40) { | |
int j = random(10,30); // brighten all | |
stateVars.jitterR = j; | |
stateVars.jitterG = j; | |
stateVars.jitterB = j; | |
}else if (r < 60) { | |
stateVars.jitterR = random(15, 25); // postive/negative color swing | |
stateVars.jitterG = random(15, 25); | |
stateVars.jitterB = random(15, 25); | |
stateVars.jitterR *= random(100) % 2 == 0? 1 : -1; | |
stateVars.jitterG *= random(100) % 2 == 0? 1 : -1; | |
stateVars.jitterB *= random(100) % 2 == 0? 1 : -1; | |
} else { | |
stateVars.jitterR = random(10,30); // random positive | |
stateVars.jitterG = random(10,30); | |
stateVars.jitterB = random(10,30); | |
} | |
} | |
if (0 < stateVars.jitterIterations) { | |
stateVars.jitterIterations--; | |
stateVars.currRenderColor.r = stateVars.AddJitter(stateVars.currRenderColor.r, stateVars.jitterR); | |
stateVars.currRenderColor.g = stateVars.AddJitter(stateVars.currRenderColor.g, stateVars.jitterG); | |
stateVars.currRenderColor.b = stateVars.AddJitter(stateVars.currRenderColor.b, stateVars.jitterB); | |
} | |
DigisparkRGB(RED, stateVars.currRenderColor.r); | |
DigisparkRGB(GREEN, stateVars.currRenderColor.g); | |
DigisparkRGB(BLUE, stateVars.currRenderColor.b); | |
DigisparkRGBDelay(DELAY_MS); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment