#include <Adafruit_NeoPixel.h>
#include <FastLED.h>
#include "water_torture.h"
#include <math.h>
#include <SoftwareSerial.h>
#define N_PIXELS 384
#define N_PIXELS_HALF (N_PIXELS/2)
#define LED_PIN 2
#define SPEED .20
#define LAST_PIXEL_OFFSET N_PIXELS-1
#define POT_PIN 4
#define BG 0
#define SPARKING 50
#define COOLING 55
#define FRAMES_PER_SECOND 60
#define NUM_BALLS 3
#define GRAVITY -9.81
#define h0 1
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif
#define BRIGHTNESS 100
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define COLOR_MIN 0
#define COLOR_MAX 255
#define DRAW_MAX 100
#define SEGMENTS 4
#define COLOR_WAIT_CYCLES 10
#define qsubd(x, b) ((x>b)?b:0)
#define qsuba(x, b) ((x>b)?x-b:0)
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
float h[NUM_BALLS] ;
float vImpact0 = sqrt( -2 * GRAVITY * h0 );
float vImpact[NUM_BALLS] ;
float tCycle[NUM_BALLS] ;
int pos[NUM_BALLS] ;
long tLast[NUM_BALLS] ;
float COR[NUM_BALLS] ;
int CYCLE_MIN_MILLIS = 2;
int CYCLE_MAX_MILLIS = 1000;
int cycleMillis = 20;
bool paused = false;
long lastTime = 0;
bool boring = true;
bool gReverseDirection = false;
int myhue = 0;
struct CRGB leds[N_PIXELS];
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
static uint16_t dist;
uint16_t scale = 30;
uint8_t maxChanges = 48;
CRGBPalette16 currentPalette(OceanColors_p);
CRGBPalette16 targetPalette(CloudColors_p);
WaterTorture water_torture = WaterTorture(&strip);
enum
{
} MODE;
bool reverse = true;
int BRIGHTNESS_MAX = 80;
int brightness = 20;
uint8_t colour;
uint8_t myfade = 255;
#define maxsteps 16
int peakspersec = 0;
int peakcount = 0;
uint8_t bgcol = 0;
int thisdelay = 20;
uint8_t thisbeat = 23;
uint8_t thatbeat = 28;
uint8_t thisfade = 2;
uint8_t thissat = 255;
uint8_t thisbri = 255;
uint8_t numdots = 4;
uint8_t faderate = 2;
uint8_t hueinc = 16;
uint8_t thishue = 0;
uint8_t curhue = 0;
uint8_t thisbright = 255;
uint8_t basebeat = 5;
uint8_t max_bright = 255;
float redStates[N_PIXELS];
float blueStates[N_PIXELS];
float greenStates[N_PIXELS];
float Fade = 0.96;
unsigned int sample;
int color;
int center = 0;
int step = -1;
int maxSteps = 16;
float fadeRate = 0.80;
int diff;
uint32_t currentBg = random(256);
uint32_t nextBg = currentBg;
TBlendType currentBlending;
const int buttonPin = 0;
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;
byte peak = 16;
byte dotCount = 0;
byte dotHangCount = 0;
void setup() {
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);
strip.begin();
strip.show();
Serial.begin(57600);
delay(3000);
LEDS.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,N_PIXELS).setCorrection(TypicalLEDStrip);
LEDS.setBrightness(BRIGHTNESS);
dist = random16(12345);
for (int i = 0 ; i < NUM_BALLS ; i++) {
tLast[i] = millis();
h[i] = h0;
pos[i] = 0;
vImpact[i] = vImpact0;
tCycle[i] = 0;
COR[i] = 0.90 - float(i)/pow(NUM_BALLS,2);
}
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState != lastButtonState) {
if (buttonState == HIGH) {
buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter);
if(buttonPushCounter==12) {
buttonPushCounter=1;}
}
else {
Serial.println(F("off"));
}
}
lastButtonState = buttonState;
switch (buttonPushCounter){
case 1:
buttonPushCounter==1; {
All();
break;}
case 2:
buttonPushCounter==2; {
rainbow(20);
break;}
case 3:
buttonPushCounter==3; {
ripple();
break;}
case 4:
buttonPushCounter==4; {
ripple2();
break;}
case 5:
buttonPushCounter==5; {
Twinkle();
break;}
case 6:
buttonPushCounter==6; {
pattern2();
break;}
case 7:
buttonPushCounter==7; {
pattern3();
break;}
case 8:
buttonPushCounter==8; {
fire();
break;}
case 9:
buttonPushCounter==9; {
Balls();
break;}
case 10:
buttonPushCounter==10; {
blur();
break;}
case 11:
buttonPushCounter==11; {
Drip();
break;}
}
}
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
if (digitalRead(buttonPin) != lastButtonState)
return;
delay(wait);
}}
void Balls() {
for (int i = 0 ; i < NUM_BALLS ; i++) {
tCycle[i] = millis() - tLast[i] ;
h[i] = 0.5 * GRAVITY * pow( tCycle[i]/1000 , 2.0 ) + vImpact[i] * tCycle[i]/1000;
if ( h[i] < 0 ) {
h[i] = 0;
vImpact[i] = COR[i] * vImpact[i] ;
tLast[i] = millis();
if ( vImpact[i] < 0.01 ) vImpact[i] = vImpact0;
}
pos[i] = round( h[i] * (N_PIXELS - 1) / h0);
}
for (int i = 0 ; i < NUM_BALLS ; i++) leds[pos[i]] = CHSV( uint8_t (i * 40) , 255, 255);
FastLED.show();
for (int i = 0 ; i < NUM_BALLS ; i++) {
leds[pos[i]] = CRGB::Black;
}
}
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) {
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
if (digitalRead(buttonPin) != lastButtonState)
return;
delay(wait);
}
}
void ripple() {
if (currentBg == nextBg) {
nextBg = random(256);
}
else if (nextBg > currentBg) {
currentBg++;
} else {
currentBg--;
}
for(uint16_t l = 0; l < N_PIXELS; l++) {
leds[l] = CHSV(currentBg, 255, 50);
}
if (step == -1) {
center = random(N_PIXELS);
color = random(256);
step = 0;
}
if (step == 0) {
leds[center] = CHSV(color, 255, 255);
step ++;
}
else {
if (step < maxSteps) {
Serial.println(pow(fadeRate,step));
leds[wrap(center + step)] = CHSV(color, 255, pow(fadeRate, step)*255);
leds[wrap(center - step)] = CHSV(color, 255, pow(fadeRate, step)*255);
if (step > 3) {
leds[wrap(center + step - 3)] = CHSV(color, 255, pow(fadeRate, step - 2)*255);
leds[wrap(center - step + 3)] = CHSV(color, 255, pow(fadeRate, step - 2)*255);
}
step ++;
}
else {
step = -1;
}
}
LEDS.show();
delay(50);
}
int wrap(int step) {
if(step < 0) return N_PIXELS + step;
if(step > N_PIXELS - 1) return step - N_PIXELS;
return step;
}
void one_color_allHSV(int ahue, int abright) {
for (int i = 0 ; i < N_PIXELS; i++ ) {
leds[i] = CHSV(ahue, 255, abright);
}
}
void ripple2() {
if (BG){
if (currentBg == nextBg) {
nextBg = random(256);
}
else if (nextBg > currentBg) {
currentBg++;
} else {
currentBg--;
}
for(uint16_t l = 0; l < N_PIXELS; l++) {
strip.setPixelColor(l, Wheel(currentBg, 0.1));
}
} else {
for(uint16_t l = 0; l < N_PIXELS; l++) {
strip.setPixelColor(l, 0, 0, 0);
}
}
if (step == -1) {
center = random(N_PIXELS);
color = random(256);
step = 0;
}
if (step == 0) {
strip.setPixelColor(center, Wheel(color, 1));
step ++;
}
else {
if (step < maxSteps) {
strip.setPixelColor(wrap(center + step), Wheel(color, pow(fadeRate, step)));
strip.setPixelColor(wrap(center - step), Wheel(color, pow(fadeRate, step)));
if (step > 3) {
strip.setPixelColor(wrap(center + step - 3), Wheel(color, pow(fadeRate, step - 2)));
strip.setPixelColor(wrap(center - step + 3), Wheel(color, pow(fadeRate, step - 2)));
}
step ++;
}
else {
step = -1;
}
}
strip.show();
delay(50);
}
void fire(){
#define FRAMES_PER_SECOND 40
random16_add_entropy( random());
static byte heat[N_PIXELS];
for( int i = 0; i < N_PIXELS; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / N_PIXELS) + 2));
}
for( int k= N_PIXELS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
if( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160,255) );
}
for( int j = 0; j < N_PIXELS; j++) {
byte colorindex = scale8( heat[j], 240);
CRGB color = ColorFromPalette( CRGBPalette16( CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White), colorindex);
int pixelnumber;
pixelnumber = j;
leds[pixelnumber] = color;
}
FastLED.show();
}
uint32_t Wheel(byte WheelPos, float opacity) {
if(WheelPos < 85) {
return strip.Color((WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity, 0);
}
else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color((255 - WheelPos * 3) * opacity, 0, (WheelPos * 3) * opacity);
}
else {
WheelPos -= 170;
return strip.Color(0, (WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity);
}
}
void pattern2() {
sinelon();
show_at_max_brightness_for_power();
}
void sinelon() {
fadeToBlackBy( leds, N_PIXELS, thisfade);
int pos1 = beatsin16(thisbeat,0,N_PIXELS);
int pos2 = beatsin16(thatbeat,0,N_PIXELS);
leds[(pos1+pos2)/2] += CHSV( myhue++/64, thissat, thisbri);
}
void pattern3() {
ChangeMe();
juggle();
show_at_max_brightness_for_power();
}
void juggle() {
curhue = thishue;
fadeToBlackBy(leds, N_PIXELS, faderate);
for( int i = 0; i < numdots; i++) {
leds[beatsin16(basebeat+i+numdots,0,N_PIXELS)] += CHSV(curhue, thissat, thisbright);
curhue += hueinc;
}
}
void ChangeMe() {
uint8_t secondHand = (millis() / 1000) % 30;
static uint8_t lastSecond = 99;
if (lastSecond != secondHand) {
lastSecond = secondHand;
if (secondHand == 0) {numdots=1; faderate=2;}
if (secondHand == 10) {numdots=4; thishue=128; faderate=8;}
if (secondHand == 20) {hueinc=48; thishue=random8();}
}
}
void addGlitter( fract8 chanceOfGlitter) {
if( random8() < chanceOfGlitter) {
leds[random16(N_PIXELS)] += CRGB::White;
}
}
void Twinkle () {
if (random(25) == 1) {
uint16_t i = random(N_PIXELS);
if (redStates[i] < 1 && greenStates[i] < 1 && blueStates[i] < 1) {
redStates[i] = random(256);
greenStates[i] = random(256);
blueStates[i] = random(256);
}
}
for(uint16_t l = 0; l < N_PIXELS; l++) {
if (redStates[l] > 1 || greenStates[l] > 1 || blueStates[l] > 1) {
strip.setPixelColor(l, redStates[l], greenStates[l], blueStates[l]);
if (redStates[l] > 1) {
redStates[l] = redStates[l] * Fade;
} else {
redStates[l] = 0;
}
if (greenStates[l] > 1) {
greenStates[l] = greenStates[l] * Fade;
} else {
greenStates[l] = 0;
}
if (blueStates[l] > 1) {
blueStates[l] = blueStates[l] * Fade;
} else {
blueStates[l] = 0;
}
} else {
strip.setPixelColor(l, 0, 0, 0);
}
}
strip.show();
delay(10);
}
void blur() {
uint8_t blurAmount = dim8_raw( beatsin8(3,64, 192) );
blur1d( leds, N_PIXELS, blurAmount);
uint8_t i = beatsin8( 9, 0, N_PIXELS);
uint8_t j = beatsin8( 7, 0, N_PIXELS);
uint8_t k = beatsin8( 5, 0, N_PIXELS);
uint16_t ms = millis();
leds[(i+j)/2] = CHSV( ms / 29, 200, 255);
leds[(j+k)/2] = CHSV( ms / 41, 200, 255);
leds[(k+i)/2] = CHSV( ms / 73, 200, 255);
leds[(k+i+j)/3] = CHSV( ms / 53, 200, 255);
FastLED.show();
}
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
if (digitalRead(buttonPin) != lastButtonState)
return;
delay(wait);
}
}
void Drip()
{
MODE_WATER_TORTURE:
if (cycle())
{
strip.setBrightness(255);
water_torture.animate(reverse);
strip.show();
}
}
bool cycle()
{
if (paused)
{
return false;
}
if (millis() - lastTime >= cycleMillis)
{
lastTime = millis();
return true;
}
return false;
}
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {ripple, ripple2, Twinkle, pattern2, pattern3, blur, Balls, fire, Drip};
uint8_t gCurrentPatternNumber = 0;
void nextPattern()
{
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void All()
{
gPatterns[gCurrentPatternNumber]();
EVERY_N_SECONDS( 30 ) { nextPattern(); }
}