BlinkenLights.ino 12.4 KB
Newer Older
Mitchell Pomery's avatar
Mitchell Pomery committed
1
/**
Mitchell Pomery's avatar
Mitchell Pomery committed
2 3
 BlinkenLights
 
Mitchell Pomery's avatar
Mitchell Pomery committed
4 5 6 7 8 9
 Code by Mitchell Pomery [BG3] with help from Andrew Adamson [BOB]
 Hardware by Andrew Adamson [BOB] with help from Mitchell Pomery [BG3]
 
 Get the dates from the git commits.
 
 The LED strip should be wired from the top left corner and zig zag down
Mitchell Pomery's avatar
Mitchell Pomery committed
10 11 12 13 14 15
 
 */

///TODO: Vary light pattern randomly
///TODO: Make run when no network is present
///TODO: Recover when network reappears
Mitchell Pomery's avatar
Mitchell Pomery committed
16
///TODO: Make everything use posts. maybe
Mitchell Pomery's avatar
Mitchell Pomery committed
17
///TODO: Sanity checks. Everywhere. Until I'm Insane.
Mitchell Pomery's avatar
Mitchell Pomery committed
18
///TODO: Figure out rough memory usage. If we max memory we will see weird behaviour.
Mitchell Pomery's avatar
Mitchell Pomery committed
19 20 21 22 23 24 25 26 27 28 29

#include <Ethernet.h> // Needed For Reasons
#include <WebServer.h> // Lets us easily do web requests
#include <SPI.h> // Needed to control Lights
#include <Adafruit_NeoPixel.h> // Controls the Lights

#define PIN 6 // Pin that the LED strip is attached to
#define PREFIX "" // Document root for our pages
#define PORT 80 // Web Server Port
#define NAMELEN 8 // Max variable length in request
#define VALUELEN 256 // Max value from request
Mitchell Pomery's avatar
Mitchell Pomery committed
30 31 32
#define WIDTH 7 // How many LEDs wide our array is
#define HEIGHT 6 // How many LEDs high our array is
#define STRIPLENGTH 42 // Number of LED's in light strip
Mitchell Pomery's avatar
Mitchell Pomery committed
33
#define NUMSEQUENCES 8 // Number predefined sequences
Mitchell Pomery's avatar
Mitchell Pomery committed
34 35 36 37 38 39 40 41

// Used to store the LED's values
struct led {
  char red;
  char green;
  char blue;
};

Mitchell Pomery's avatar
Mitchell Pomery committed
42 43 44 45 46
// Used for our default light sequences
char red = (int) 255;
char green = (int) 255;
char blue = (int) 255;

Mitchell Pomery's avatar
Mitchell Pomery committed
47
// For controlling the lights - Should only be changed by the functions
Mitchell Pomery's avatar
Mitchell Pomery committed
48 49
int position = 0; // How far through the cycle we are
struct led ledArray[STRIPLENGTH]; // led array
50
int lightOption = 1; // Which predefined light sequence we are running
Mitchell Pomery's avatar
Mitchell Pomery committed
51 52 53
char brightness = (char) 128; //Brightness of the LEDs
  // We seem to have issues at the moment putting this up to the maximum (255)
  // Most likely due to the fact the LED strip is underpowered
Mitchell Pomery's avatar
Mitchell Pomery committed
54

Mitchell Pomery's avatar
Mitchell Pomery committed
55
// Network Settings
Mitchell Pomery's avatar
Mitchell Pomery committed
56
static uint8_t mac[] = { 0xC0, 0xCA, 0xC0, 0x1A, 0x19, 0x82 }; // C0CA C01A 1982
Mitchell Pomery's avatar
Mitchell Pomery committed
57
IPAddress ip(130,95,13,96); // 130.95.13.96 (Can we forcefully take .82?
Mitchell Pomery's avatar
Mitchell Pomery committed
58
// If we remove the ip address, we will automatically use DHCP
Mitchell Pomery's avatar
Mitchell Pomery committed
59 60

// Set up our light strip
Mitchell Pomery's avatar
Mitchell Pomery committed
61 62
Adafruit_NeoPixel strip = Adafruit_NeoPixel(STRIPLENGTH, PIN,
  NEO_GRB + NEO_KHZ800);
Mitchell Pomery's avatar
Mitchell Pomery committed
63 64 65
// Set up our webserver
WebServer webserver(PREFIX, 80);

Mitchell Pomery's avatar
Mitchell Pomery committed
66 67
// ============================ LIGHT MANIPULATION ============================

Mitchell Pomery's avatar
Mitchell Pomery committed
68 69
/**
 * Change the lights to our updated array
Mitchell Pomery's avatar
Mitchell Pomery committed
70
 * We should probably get rid of this soonish
Mitchell Pomery's avatar
Mitchell Pomery committed
71
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
72
void updateLights() {
Mitchell Pomery's avatar
Mitchell Pomery committed
73
  for (int i = 0; i < STRIPLENGTH; i ++) {
Mitchell Pomery's avatar
Mitchell Pomery committed
74
    strip.setPixelColor(i, (int) ledArray[i].red, (int) ledArray[i].green, (int) ledArray[i].blue);
Mitchell Pomery's avatar
Mitchell Pomery committed
75 76 77 78
  }
  strip.show();
}

Mitchell Pomery's avatar
Mitchell Pomery committed
79
/**
Mitchell Pomery's avatar
Mitchell Pomery committed
80
 * go from (x,y) to position in the array
Mitchell Pomery's avatar
Mitchell Pomery committed
81 82
 * @param xpos  x coordinate
 * @param ypos  y cordinate
Mitchell Pomery's avatar
Mitchell Pomery committed
83
 * @return      position in the array, -1 if out of array
Mitchell Pomery's avatar
Mitchell Pomery committed
84 85 86 87
 */
int coordToPos(int xpos, int ypos) {
  ///TODO: Test this function
  int pos = 0;
Mitchell Pomery's avatar
Mitchell Pomery committed
88 89 90
  if ((xpos < 0 || xpos >= WIDTH) || (ypos < 0 || ypos >= HEIGHT)) {
    return -1;
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104
  if (ypos % 2 == 0) { // if we are on an even line, add y
    pos = ypos * WIDTH + xpos;
  }
  else { // on an odd line, take y
    if (WIDTH % 2 == 0) { // even width
      pos = ypos * WIDTH + HEIGHT - xpos;
    }
    else { // odd width
      pos = ypos * WIDTH + HEIGHT - xpos -1;
    }
  }
  return pos;
}

Mitchell Pomery's avatar
Mitchell Pomery committed
105
/**
Mitchell Pomery's avatar
Mitchell Pomery committed
106
 * Set the LED at pos in the strip to the defined colour
Mitchell Pomery's avatar
Mitchell Pomery committed
107
 * @param pos   position in the array
Mitchell Pomery's avatar
Mitchell Pomery committed
108 109 110
 * @param red   red portion of colour
 * @param green green portion of colour
 * @param blue  blue portion of colour
Mitchell Pomery's avatar
Mitchell Pomery committed
111
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
112
void setLED(int pos, int red, int green, int blue) {
Mitchell Pomery's avatar
Mitchell Pomery committed
113 114 115 116 117
  if (pos > 0 && pos < STRIPLENGTH) {
    ledArray[pos].red = red;
    ledArray[pos].green = green;
    ledArray[pos].blue = blue;
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
118 119
}

Mitchell Pomery's avatar
Mitchell Pomery committed
120
/**
Mitchell Pomery's avatar
Mitchell Pomery committed
121
 * Set the LED at (xpos, ypos) in the strip to the defined colour
Mitchell Pomery's avatar
Mitchell Pomery committed
122 123
 * @param xpos  x coordinate
 * @param ypos  y coordinate
Mitchell Pomery's avatar
Mitchell Pomery committed
124 125 126
 * @param red   red portion of colour
 * @param green green portion of colour
 * @param blue  blue portion of colour
Mitchell Pomery's avatar
Mitchell Pomery committed
127
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
128 129
void setLED(int xpos, int ypos, int red, int green, int blue) {
  int pos = coordToPos(xpos, ypos);
Mitchell Pomery's avatar
Mitchell Pomery committed
130 131 132 133
  setLED(pos, red, green, blue);
}

/**
Mitchell Pomery's avatar
Mitchell Pomery committed
134 135
 * Get the colour of the LED in pos position in the strip
 * @param pos   position in the strip
Mitchell Pomery's avatar
Mitchell Pomery committed
136
 * @return      colour of LED at pos
Mitchell Pomery's avatar
Mitchell Pomery committed
137 138 139 140 141
 */
struct led getLED(int pos) {
  return ledArray[pos];
}

Mitchell Pomery's avatar
Mitchell Pomery committed
142 143 144 145
/**
 * Get the colour of the LED at (xpos, ypos)
 * @param xpos  x coordinate
 * @param ypos  y coordinate
Mitchell Pomery's avatar
Mitchell Pomery committed
146
 * @return      colour of LED at (xpos, ypos)
Mitchell Pomery's avatar
Mitchell Pomery committed
147 148 149 150 151 152 153 154 155 156 157 158
 */
struct led getLED(int xpos, int ypos) {
  int pos = coordToPos(xpos, ypos);
  return ledArray[pos];
}

// ================================ WEB PAGES ================================

///TODO: Comment this stuff
///TODO: Reduce code reuse in the web page functions
///TODO: Make a function to set all the lights at once

Mitchell Pomery's avatar
Mitchell Pomery committed
159 160 161 162 163 164 165 166
/**
 * Sets the light sequence to one that is predefined.
 * Set it to 0 to disable the cycling of lights.
 * @param server        
 * @param type          
 * @param url_tail      
 * @param tail_complete 
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
167 168
void webSetSequence(WebServer &server, WebServer::ConnectionType type,
char *url_tail, bool tail_complete) {
Mitchell Pomery's avatar
Mitchell Pomery committed
169 170 171 172 173
  URLPARAM_RESULT rc;
  char name[NAMELEN];
  char value[VALUELEN];
  
  server.httpSuccess();
Mitchell Pomery's avatar
Mitchell Pomery committed
174
  // Kill the connection before doing anything if all they want is head
Mitchell Pomery's avatar
Mitchell Pomery committed
175 176 177
  if (type == WebServer::HEAD) {
    return;
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
178
  else if (type == WebServer::GET) {
179 180 181 182 183 184 185
    while (strlen(url_tail)) {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc != URLPARAM_EOS) {
        if (String(name).equals("seq")) {
          lightOption = atoi(value);
          server.print(lightOption);
          position = 0;
Mitchell Pomery's avatar
Mitchell Pomery committed
186 187 188 189 190
        }
      }
    }
  }
  else {
Mitchell Pomery's avatar
Mitchell Pomery committed
191
    server.print("Unknown Request");
Mitchell Pomery's avatar
Mitchell Pomery committed
192 193 194
  }
}

Mitchell Pomery's avatar
Mitchell Pomery committed
195 196 197 198 199 200 201
/**
 * Set a specific LED to a specific colour
 * @param server        
 * @param type          
 * @param url_tail      
 * @param tail_complete 
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
202 203
void webSetLED(WebServer &server, WebServer::ConnectionType type,
char *url_tail, bool tail_complete) {
Mitchell Pomery's avatar
Mitchell Pomery committed
204 205 206 207 208 209 210 211 212 213
  URLPARAM_RESULT rc;
  char name[NAMELEN];
  char value[VALUELEN];
  int xPos = -1;
  int yPos = -1;
  int r = -1;
  int g = -1;
  int b = -1;
  
  server.httpSuccess();
Mitchell Pomery's avatar
Mitchell Pomery committed
214
  // Kill the connection before doing anything if all they want is head
Mitchell Pomery's avatar
Mitchell Pomery committed
215 216 217
  if (type == WebServer::HEAD) {
    return;
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
218
  else if (type == WebServer::GET) {
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
    while (strlen(url_tail)) {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc != URLPARAM_EOS) {
        if (String(name).equals("x")) {
          xPos = atoi(value);
        }
        else if (String(name).equals("y")) {
          yPos = atoi(value);
        }
        else if (String(name).equals("r")) {
          r = atoi(value);
        }
        else if (String(name).equals("g")) {
          g = atoi(value);
        }
        else if (String(name).equals("b")) {
          b = atoi(value);
Mitchell Pomery's avatar
Mitchell Pomery committed
236 237 238 239 240 241 242 243 244 245 246 247
        }
      }
    }
  }
  else {
    server.print("Unknown");
  }
  if (xPos != -1 && yPos != -1 && r != -1 && g != -1 && b != -1) {
    setLED(xPos, r, g, b);
  }
}

Mitchell Pomery's avatar
Mitchell Pomery committed
248 249 250 251 252 253 254
/**
 * Set the brightness to a specific magnitude
 * @param server        
 * @param type          
 * @param url_tail      
 * @param tail_complete 
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
255 256
void webSetBrightness(WebServer &server, WebServer::ConnectionType type,
char *url_tail, bool tail_complete) {
Mitchell Pomery's avatar
Mitchell Pomery committed
257 258 259 260 261
  URLPARAM_RESULT rc;
  char name[NAMELEN];
  char value[VALUELEN];
  
  server.httpSuccess();
Mitchell Pomery's avatar
Mitchell Pomery committed
262
  // Kill the connection before doing anything if all they want is head
Mitchell Pomery's avatar
Mitchell Pomery committed
263 264 265 266
  if (type == WebServer::HEAD) {
    return;
  }
  else if (type == WebServer::GET) { //WebServer::POST
267 268 269 270 271 272 273
    while (strlen(url_tail)) {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc != URLPARAM_EOS) {
        if (String(name).equals("bright")) {
          strip.setBrightness(atoi(value));
          server.print(atoi(value));
          strip.show();
Mitchell Pomery's avatar
Mitchell Pomery committed
274 275 276 277 278 279 280 281 282
        }
      }
    }
  }
  else {
    server.print("Unknown");
  }
}

Mitchell Pomery's avatar
Mitchell Pomery committed
283 284
// ============================== LIGHT DISPLAYS ==============================

Mitchell Pomery's avatar
Mitchell Pomery committed
285 286 287 288 289 290
/**
 * Fill the dots one after the other with a colour
 * @param colour colour to fill the array with
 * @param wait  delay between colour changes
 */
void colourWipe(uint32_t c, uint8_t wait) {
Mitchell Pomery's avatar
Mitchell Pomery committed
291 292 293 294
  strip.setPixelColor(position, c);
  strip.show();
  delay(wait);
  position++;
Mitchell Pomery's avatar
Mitchell Pomery committed
295
  if (position >= STRIPLENGTH) {
Mitchell Pomery's avatar
Mitchell Pomery committed
296
    position = 256;
Mitchell Pomery's avatar
Mitchell Pomery committed
297 298 299
  }
}

Mitchell Pomery's avatar
Mitchell Pomery committed
300
/**
Mitchell Pomery's avatar
Mitchell Pomery committed
301
 * Turn the light strip into a rainbow
Mitchell Pomery's avatar
Mitchell Pomery committed
302 303
 * @param wait  delay between colour changes
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
304
void rainbow(uint8_t wait) {
Mitchell Pomery's avatar
Mitchell Pomery committed
305 306
  int outOf = 256;
  for (int i = 0; i < strip.numPixels(); i++) {
Mitchell Pomery's avatar
Mitchell Pomery committed
307
    strip.setPixelColor(i, Wheel((i+position) & 255));
Mitchell Pomery's avatar
Mitchell Pomery committed
308 309 310 311
  }
  strip.show();
  delay(wait);
  position++;
Mitchell Pomery's avatar
Mitchell Pomery committed
312 313 314
  if (position > outOf) {
    position = 0;
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
315 316
}

Mitchell Pomery's avatar
Mitchell Pomery committed
317 318 319 320
/**
 * Slightly different, this makes the rainbow equally distributed throughout
 * @param wait  delay between colour changes
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
321
void rainbowCycle(uint8_t wait) {
Mitchell Pomery's avatar
Mitchell Pomery committed
322 323 324 325
  int outOf = 256 * 5;
  uint16_t i;
  for(i=0; i< strip.numPixels(); i++) {
    strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + position) & 255));
Mitchell Pomery's avatar
Mitchell Pomery committed
326 327 328 329
  }
  strip.show();
  delay(wait);
  position++;
Mitchell Pomery's avatar
Mitchell Pomery committed
330 331
  if (position >= outOf) {
    position = 0;
Mitchell Pomery's avatar
Mitchell Pomery committed
332 333 334
  }
}

Mitchell Pomery's avatar
Mitchell Pomery committed
335 336 337 338 339
/**
 * Theatre-style crawling lights.
 * @param colour colour to fill the array with
 * @param wait  delay between colour changes
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
340
void theaterChase(uint32_t c, uint8_t wait) {
Mitchell Pomery's avatar
Mitchell Pomery committed
341
  ///TODO: stop this blocking. Somehow
Mitchell Pomery's avatar
Mitchell Pomery committed
342 343 344 345 346 347 348 349 350
  int outOf = 10;
  for (int q=0; q < 3; q++) {
    for (int i=0; i < strip.numPixels(); i=i+3) {
      strip.setPixelColor(i+q, c); // turn every third pixel on
    }
    strip.show();
    delay(wait);
    for (int i=0; i < strip.numPixels(); i=i+3) {
      strip.setPixelColor(i+q, 0); // turn every third pixel off
Mitchell Pomery's avatar
Mitchell Pomery committed
351 352
    }
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
353 354 355 356
  position++;
  if (position >= outOf) {
    position = 0;
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
357 358
}

Mitchell Pomery's avatar
Mitchell Pomery committed
359 360 361 362
/**
 * Theatre-style crawling lights with rainbow effect
 * @param wait  delay between colour changes
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
363
void theaterChaseRainbow(uint8_t wait) {
Mitchell Pomery's avatar
Mitchell Pomery committed
364
  ///TODO: stop this blocking. Somehow
Mitchell Pomery's avatar
Mitchell Pomery committed
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
  int outOf = 256;
  for (int q=0; q < 3; q++) {
      for (int i=0; i < strip.numPixels(); i=i+3) {
        // turn every third pixel on
        strip.setPixelColor(i+q, Wheel( (i+position) % 255));
      }
      strip.show();
     
      delay(wait);
     
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0); // turn every third pixel off
      }
  }
  
  position++;
  if (position >= outOf) {
    position = 0;
Mitchell Pomery's avatar
Mitchell Pomery committed
383 384 385
  }
}

Mitchell Pomery's avatar
Mitchell Pomery committed
386 387 388 389 390 391
/**
 * Input a value 0 to 255 to get a colour value.
 * The colours are a transition r - g - b - back to r.
 * @param WheelPos  Where we currently are in the cycle
 * @return          A new colour
 */
Mitchell Pomery's avatar
Mitchell Pomery committed
392 393
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
Mitchell Pomery's avatar
Mitchell Pomery committed
394
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
Mitchell Pomery's avatar
Mitchell Pomery committed
395 396
  } else if(WheelPos < 170) {
   WheelPos -= 85;
Mitchell Pomery's avatar
Mitchell Pomery committed
397
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
Mitchell Pomery's avatar
Mitchell Pomery committed
398 399
  } else {
   WheelPos -= 170;
Mitchell Pomery's avatar
Mitchell Pomery committed
400
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
Mitchell Pomery's avatar
Mitchell Pomery committed
401 402 403
  }
}

Mitchell Pomery's avatar
Mitchell Pomery committed
404 405
// =============================== MAIN PROGRAM ===============================

Mitchell Pomery's avatar
Mitchell Pomery committed
406 407
///TODO: Comment this stuff

Mitchell Pomery's avatar
Mitchell Pomery committed
408
void setup() {
Mitchell Pomery's avatar
Mitchell Pomery committed
409 410 411
  Serial.begin(9600);
  while(!Serial);
  Serial.println("Starting Ethernet");
Mitchell Pomery's avatar
Mitchell Pomery committed
412
  // Start Ethernet
Mitchell Pomery's avatar
Mitchell Pomery committed
413
  Ethernet.begin(mac, ip);
Mitchell Pomery's avatar
Mitchell Pomery committed
414
  Serial.println("Ethernet Started");
Mitchell Pomery's avatar
Mitchell Pomery committed
415
  // Set up webpages
Mitchell Pomery's avatar
Mitchell Pomery committed
416 417 418 419
  webserver.setDefaultCommand(&webSetSequence);
  webserver.addCommand("custom", &webSetSequence);
  webserver.addCommand("individual", &webSetLED);
  webserver.addCommand("brightness", &webSetBrightness);
Mitchell Pomery's avatar
Mitchell Pomery committed
420
  // Start Webserver
Mitchell Pomery's avatar
Mitchell Pomery committed
421
  webserver.begin();
Mitchell Pomery's avatar
Mitchell Pomery committed
422
  // Turn our lights on
Mitchell Pomery's avatar
Mitchell Pomery committed
423 424 425 426 427 428 429 430
  for (int i = 0; i < STRIPLENGTH; i ++) {
    ledArray[i].red = (char) 128;
    ledArray[i].green = (char) 128;
    ledArray[i].blue = (char) 128;
  }
  
  // Start Lights
  strip.begin();
Mitchell Pomery's avatar
Mitchell Pomery committed
431
  strip.setBrightness(128);
Mitchell Pomery's avatar
Mitchell Pomery committed
432
  updateLights();
Mitchell Pomery's avatar
Mitchell Pomery committed
433 434 435 436 437 438 439 440
}

void loop()
{
  // process incoming connections one at a time forever
  char buff[64];
  int len = 64;
  webserver.processConnection(buff, &len);
Mitchell Pomery's avatar
Mitchell Pomery committed
441
  if (lightOption > NUMSEQUENCES) {
Mitchell Pomery's avatar
Mitchell Pomery committed
442
    //lightOption = 1;
Mitchell Pomery's avatar
Mitchell Pomery committed
443
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
444
  
Mitchell Pomery's avatar
Mitchell Pomery committed
445
  // Run our light sequence after checking for we requests
Mitchell Pomery's avatar
Mitchell Pomery committed
446
  ///TODO: Make these switches nicer
Mitchell Pomery's avatar
Mitchell Pomery committed
447 448
  switch (lightOption) {
    case 0: // Don't change the lights at all
Mitchell Pomery's avatar
Mitchell Pomery committed
449
      break;
450 451 452 453 454
    case 1: // RainbowCycle
      rainbowCycle(20);
      break;
    // Cycling through LED Sequences
    case 11:
Mitchell Pomery's avatar
Mitchell Pomery committed
455 456
      colourWipe(strip.Color(red, green, blue), 50);
      Serial.println("ColourWipe");
Mitchell Pomery's avatar
Mitchell Pomery committed
457
      break;
458
    case 12:
Mitchell Pomery's avatar
Mitchell Pomery committed
459 460
      rainbow(20);
      break;
461
    case 13:
Mitchell Pomery's avatar
Mitchell Pomery committed
462 463
      rainbowCycle(20);
      break;
464
    case 14:
Mitchell Pomery's avatar
Mitchell Pomery committed
465 466
      theaterChaseRainbow(20);
      break;
467 468
    default: // Go back to cycling
      lightOption = 11;
Mitchell Pomery's avatar
Mitchell Pomery committed
469
      break;
Mitchell Pomery's avatar
Mitchell Pomery committed
470
  }
471
  
Mitchell Pomery's avatar
Mitchell Pomery committed
472
  // Show our lights
473
  if (position == 0 && lightOption > 10) { // if we have completed a sequence, move to the next one
Mitchell Pomery's avatar
Mitchell Pomery committed
474 475
    lightOption++;
  }
Mitchell Pomery's avatar
Mitchell Pomery committed
476
}