adafruit_Adalight/Processing/Colorswirl/Colorswirl.pde
// "Colorswirl" LED demo.  This is the host PC-side code written in
// Processing; intended for use with a USB-connected Arduino microcontroller
// running the accompanying LED streaming code.  Requires one strand of
// Digital RGB LED Pixels (Adafruit product ID #322, specifically the newer
// WS2801-based type, strand of 25) and a 5 Volt power supply (such as
// Adafruit #276).  You may need to adapt the code and the hardware
// arrangement for your specific configuration.

// --------------------------------------------------------------------
//   This file is part of Adalight.

//   Adalight is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Lesser General Public License as
//   published by the Free Software Foundation, either version 3 of
//   the License, or (at your option) any later version.

//   Adalight is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Lesser General Public License for more details.

//   You should have received a copy of the GNU Lesser General Public
//   License along with Adalight.  If not, see
//   <http://www.gnu.org/licenses/>.
// --------------------------------------------------------------------

import processing.serial.*;

int N_LEDS = 25; // Max of 65536

void setup()
{
  byte[] buffer = new byte[6 + N_LEDS * 3];
  Serial myPort;
  int    i, hue1, hue2, bright, lo, r, g, b, t, prev, frame = 0;
  long   totalBytesSent = 0;
  float  sine1, sine2;

  noLoop();

  // Assumes the Arduino is the first/only serial device.  If this is not the
  // case, change the device index here.  println(Serial.list()); can be used
  // to get a list of available serial devices.
  myPort = new Serial(this, Serial.list()[0], 115200);

  // A special header / magic word is expected by the corresponding LED
  // streaming code running on the Arduino.  This only needs to be initialized
  // once because the number of LEDs remains constant:
  buffer[0] = 'A';                                // Magic word
  buffer[1] = 'd';
  buffer[2] = 'a';
  buffer[3] = byte((N_LEDS - 1) >> 8);            // LED count high byte
  buffer[4] = byte((N_LEDS - 1) & 0xff);          // LED count low byte
  buffer[5] = byte(buffer[3] ^ buffer[4] ^ 0x55); // Checksum

  sine1 = 0.0;
  hue1  = 0;
  prev  = second(); // For bandwidth statistics

  for (;;) {
    sine2 = sine1;
    hue2  = hue1;

    // Start at position 6, after the LED header/magic word
    for (i = 6; i < buffer.length; ) {
      // Fixed-point hue-to-RGB conversion.  'hue2' is an integer in the
      // range of 0 to 1535, where 0 = red, 256 = yellow, 512 = green, etc.
      // The high byte (0-5) corresponds to the sextant within the color
      // wheel, while the low byte (0-255) is the fractional part between
      // the primary/secondary colors.
      lo = hue2 & 255;
      switch((hue2 >> 8) % 6) {
      case 0:
        r = 255;
        g = lo;
        b = 0;
        break;
      case 1:
        r = 255 - lo;
        g = 255;
        b = 0;
        break;
      case 2:
        r = 0;
        g = 255;
        b = lo;
        break;
      case 3:
        r = 0;
        g = 255 - lo;
        b = 255;
        break;
      case 4:
        r = lo;
        g = 0;
        b = 255;
        break;
      default:
        r = 255;
        g = 0;
        b = 255 - lo;
        break;
      }

      // Resulting hue is multiplied by brightness in the range of 0 to 255
      // (0 = off, 255 = brightest).  Gamma corrrection (the 'pow' function
      // here) adjusts the brightness to be more perceptually linear.
      bright      = int(pow(0.5 + sin(sine2) * 0.5, 2.8) * 255.0);
      buffer[i++] = byte((r * bright) / 255);
      buffer[i++] = byte((g * bright) / 255);
      buffer[i++] = byte((b * bright) / 255);

      // Each pixel is slightly offset in both hue and brightness
      hue2  += 40;
      sine2 += 0.3;
    }

    // Slowly rotate hue and brightness in opposite directions
    hue1   = (hue1 + 4) % 1536;
    sine1 -= .03;

    // Issue color data to LEDs and keep track of the byte and frame counts
    myPort.write(buffer);
    totalBytesSent += buffer.length;
    frame++;

    // Update statistics once per second
    if ((t = second()) != prev) {
      print("Average frames/sec: ");
      print(int((float)frame / (float)millis() * 1000.0));
      print(", bytes/sec: ");
      println(int((float)totalBytesSent / (float)millis() * 1000.0));
      prev = t;
    }
  }
}

void draw()
{
}

