[
  {
    "path": ".arduino-ci.yaml",
    "content": "skip_boards:\n  - arduino:samd:arduino_zero_native\n  - Intel:arc32:arduino_101\n  - esp8266:esp8266:huzzah\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report-or-feature-request.md",
    "content": "---\nname: Bug report or feature request\nabout: Did you find a specific bug in the code for this project? Do you want to request\n  a new feature? Please open an issue!\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Pololu Forum\n    url: https://forum.pololu.com/\n    about: Do you need help getting started? Can't get this code to work at all? Having problems with electronics? Please post on our forum!\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "name: \"CI\"\non:\n  pull_request:\n  push:\njobs:\n  ci:\n    runs-on: ubuntu-20.04\n    steps:\n    - name: Checkout this repository\n      uses: actions/checkout@v2.3.4\n    - name: Cache for arduino-ci\n      uses: actions/cache@v2.1.3\n      with:\n        path: |\n          ~/.arduino15\n        key: ${{ runner.os }}-arduino\n    - name: Install nix\n      uses: cachix/install-nix-action@v12\n    - run: nix-shell -I nixpkgs=channel:nixpkgs-unstable -p arduino-ci --run \"arduino-ci\"\n"
  },
  {
    "path": ".gitignore",
    "content": "/docs/\n/out/\n"
  },
  {
    "path": ".gitlab-ci.yml",
    "content": "image: $CI_REGISTRY_IMAGE/nixos/nix:2.3.6\n\nstages:\n  - ci\n\nci:\n  stage: ci\n  tags:\n    - nix\n  script:\n    - nix-shell -I nixpkgs=channel:nixpkgs-unstable -p arduino-ci --run \"arduino-ci\"\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Copyright (c) 2012-2020 Pololu Corporation (www.pololu.com)\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "PololuLedStrip.cpp",
    "content": "#include <PololuLedStrip.h>\n\nbool PololuLedStripBase::interruptFriendly = false;"
  },
  {
    "path": "PololuLedStrip.h",
    "content": "#pragma once\n\n#include <Arduino.h>\n\n#if defined(__AVR__)\n#include <avr/io.h>\n#include <avr/interrupt.h>\n#include <util/delay.h>\n\n#define __enable_irq sei\n#define __disable_irq cli\n\n#if !(F_CPU == 8000000 || F_CPU == 12000000 || F_CPU == 16000000 || F_CPU == 20000000)\n#error \"On an AVR, this version of the PololuLedStrip library only supports 8, 12, 16, and 20 MHz.\"\n#endif\n\n#elif defined(__arm__)\n\n#if !(F_CPU == 84000000)\n#error \"On an ARM, this version of the PololuLedStrip library only supports 84 MHz.\"\n#endif\n\n#endif\n\nnamespace Pololu\n{\n  #ifndef _POLOLU_RGB_COLOR\n  #define _POLOLU_RGB_COLOR\n  typedef struct rgb_color\n  {\n    unsigned char red, green, blue;\n    rgb_color() {};\n    rgb_color(uint8_t r, uint8_t g, uint8_t b) : red(r), green(g), blue(b) {};\n  } rgb_color;\n  #endif\n\n  class PololuLedStripBase\n  {\n    public:\n    static bool interruptFriendly;\n    void virtual write(rgb_color *, unsigned int count) = 0;\n  };\n\n  template<unsigned char pin> class PololuLedStrip : public PololuLedStripBase\n  {\n    public:\n    void virtual write(rgb_color *, unsigned int count);\n  };\n\n  #if defined(__AVR_ATmega32U4__)\n  // ATmega32U4-based boards such as the Arduino Leonardo\n\n  const unsigned char pinBit[] =\n  {\n    2, 3, 1, 0, 4, 6, 7, 6,  // Pins 0-7\n    4, 5, 6, 7, 6, 7,        // Pins 8-13\n    3, 1, 2, 0,              // Pins 14-17\n    7, 6, 5, 4, 1, 0,        // Pins 18-23\n    4, 7, 4, 5, 6, 6,        // Pins 24-29\n  };\n\n  const unsigned char pinAddr[] =\n  {\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTE),\n\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTC),\n\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTD),\n  };\n\n  #elif defined(__AVR_ATmega328PB__) || defined(ARDUINO_AVR_A_STAR_328PB)\n  // ATmega328PB-based boards such as the A-Star 328PB Micro\n\n  const unsigned char pinBit[] =\n  {\n    0, 1, 2, 3, 4, 5, 6, 7,  // PORTD\n    0, 1, 2, 3, 4, 5,        // PORTB\n    0, 1, 2, 3, 4, 5,        // PORTC\n    2, 3, 0, 1,              // PORTE\n    6,                       // PORTC\n  };\n\n  const unsigned char pinAddr[] =\n  {\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTC),\n  };\n\n  #elif defined(__AVR__) && (!defined(NUM_DIGITAL_PINS) || NUM_DIGITAL_PINS == 20)\n  // ATmega168/328-based boards such as the Arduino Uno or Baby Orangutan B-328\n\n  const unsigned char pinBit[] =\n  {\n    0, 1, 2, 3, 4, 5, 6, 7,  // PORTD\n    0, 1, 2, 3, 4, 5,        // PORTB\n    0, 1, 2, 3, 4, 5, 6,     // PORTC\n  };\n\n  const unsigned char pinAddr[] =\n  {\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n  };\n\n  #elif defined(__AVR__) && NUM_DIGITAL_PINS == 70\n  // ATmega2560-based boards such as the Arduino Mega 2560\n\n  const unsigned char pinBit[] =\n  {\n    0, 1, 4, 5, 5, 3, 3, 4, 5, 6,\n    4, 5, 6, 7, 1, 0, 1, 0, 3, 2,\n    1, 0, 0, 1, 2, 3, 4, 5, 6, 7,\n    7, 6, 5, 4, 3, 2, 1, 0, 7, 2,\n    1, 0, 7, 6, 5, 4, 3, 2, 1, 0,\n    3, 2, 1, 0, 0, 1, 2, 3, 4, 5,\n    6, 7, 0, 1, 2, 3, 4, 5, 6, 7,\n  };\n\n  const unsigned char pinAddr[] =\n  {\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTG),\n    _SFR_IO_ADDR(PORTE),\n    _SFR_IO_ADDR(PORTH),\n    _SFR_IO_ADDR(PORTH),\n    _SFR_IO_ADDR(PORTH),\n    _SFR_IO_ADDR(PORTH),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTJ),\n    _SFR_IO_ADDR(PORTJ),\n    _SFR_IO_ADDR(PORTH),\n    _SFR_IO_ADDR(PORTH),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTA),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTC),\n    _SFR_IO_ADDR(PORTD),\n    _SFR_IO_ADDR(PORTG),\n    _SFR_IO_ADDR(PORTG),\n    _SFR_IO_ADDR(PORTG),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTL),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTB),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTF),\n    _SFR_IO_ADDR(PORTK),\n    _SFR_IO_ADDR(PORTK),\n    _SFR_IO_ADDR(PORTK),\n    _SFR_IO_ADDR(PORTK),\n    _SFR_IO_ADDR(PORTK),\n    _SFR_IO_ADDR(PORTK),\n    _SFR_IO_ADDR(PORTK),\n    _SFR_IO_ADDR(PORTK),\n  };\n\n  #endif\n\n  template<unsigned char pin> void __attribute__((aligned(16))) PololuLedStrip<pin>::write(rgb_color * colors, unsigned int count)\n  {\n    #if defined(__AVR__)\n    digitalWrite(pin, LOW);\n    pinMode(pin, OUTPUT);\n\n    #elif defined(__arm__)\n    Pio * port = g_APinDescription[pin].pPort;\n    uint32_t pinValue = g_APinDescription[pin].ulPin;\n    PIO_SetOutput(port, pinValue, LOW, 0, 0);\n\n    #endif\n\n    __disable_irq();   // Disable interrupts temporarily because we don't want our pulse timing to be messed up.\n\n    while (count--)\n    {\n      // Send a color to the LED strip.\n      // The assembly below also increments the 'colors' pointer,\n      // it will be pointing to the next color at the end of this loop.\n      #if defined(__AVR__)\n      asm volatile(\n        \"ld __tmp_reg__, %a0+\\n\"         // Advance pointer from red to green.\n        \"ld __tmp_reg__, %a0\\n\"          // Read the green component and leave the pointer pointing to green.\n        \"rcall send_led_strip_byte%=\\n\"  // Send green component.\n        \"ld __tmp_reg__, -%a0\\n\"         // Read the red component and leave the pointer at red.\n        \"rcall send_led_strip_byte%=\\n\"  // Send green component.\n        \"ld __tmp_reg__, %a0+\\n\"         // Advance pointer from red to green.\n        \"ld __tmp_reg__, %a0+\\n\"         // Advance pointer from green to blue.\n        \"ld __tmp_reg__, %a0+\\n\"         // Read the blue component and leave the pointer on the next color's red.\n        \"rcall send_led_strip_byte%=\\n\"  // Send blue component.\n        \"rjmp led_strip_asm_end%=\\n\"     // Jump past the assembly subroutines.\n\n        // send_led_strip_byte subroutine:  Sends a byte to the LED strip.\n        \"send_led_strip_byte%=:\\n\"\n        \"rcall send_led_strip_bit%=\\n\"  // Send most-significant bit (bit 7).\n        \"rcall send_led_strip_bit%=\\n\"\n        \"rcall send_led_strip_bit%=\\n\"\n        \"rcall send_led_strip_bit%=\\n\"\n        \"rcall send_led_strip_bit%=\\n\"\n        \"rcall send_led_strip_bit%=\\n\"\n        \"rcall send_led_strip_bit%=\\n\"\n        \"rcall send_led_strip_bit%=\\n\"  // Send least-significant bit (bit 0).\n        \"ret\\n\"\n\n        // send_led_strip_bit subroutine:  Sends single bit to the LED strip by\n        // driving the data line high for some time.\n        //\n        //           Pin state each cycle            High time  Period\n        //  8 MHz 0: LHHHLLLLLLLLLLLLL               0.375 us   2.125 us\n        //  8 MHz 1: LHHHHHHHLLLLLLLLL               0.750 us   2.125 us\n        // 12 MHz 0: HHHHLLLLLLLLLLLLLLL             0.333 us   1.583 us\n        // 12 MHz 1: HHHHHHHHHHLLLLLLLLL             0.833 us   1.583 us\n        // 16 MHz 0: HHHHHHLLLLLLLLLLLLLLLL          0.375 us   1.375 us\n        // 16 MHz 1: HHHHHHHHHHHHHLLLLLLLLL          0.813 us   1.375 us\n        // 20 MHz 0: HHHHHHHHLLLLLLLLLLLLLLLLLL      0.400 us   1.300 us\n        // 20 MHz 1: HHHHHHHHHHHHHHHHHLLLLLLLLL      0.850 us   1.300 us\n        \"send_led_strip_bit%=:\\n\"\n#if F_CPU == 8000000\n        \"rol __tmp_reg__\\n\"                      // Rotate left through carry.\n#endif\n        \"sbi %2, %3\\n\"                           // Drive the line high.\n#if F_CPU != 8000000\n        \"rol __tmp_reg__\\n\"                      // Rotate left through carry.\n#endif\n\n#if F_CPU == 16000000\n        \"nop\\n\" \"nop\\n\"\n#elif F_CPU == 20000000\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n#endif\n\n        \"brcs .+2\\n\" \"cbi %2, %3\\n\"              // If the bit to send is 0, drive the line low now.\n\n#if F_CPU == 8000000\n        \"nop\\n\" \"nop\\n\"\n#elif F_CPU == 12000000\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n#elif F_CPU == 16000000\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n#elif F_CPU == 20000000\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n        \"nop\\n\" \"nop\\n\"\n#endif\n\n        \"brcc .+2\\n\" \"cbi %2, %3\\n\"              // If the bit to send is 1, drive the line low now.\n\n        \"ret\\n\"\n        \"led_strip_asm_end%=: \"\n        : \"=b\" (colors)\n        : \"0\" (colors),         // %a0 points to the next color to display\n          \"I\" (pinAddr[pin]),   // %2 is the port register (e.g. PORTC)\n          \"I\" (pinBit[pin])     // %3 is the pin number (0-8)\n      );\n\n      #elif defined(__arm__)\n      asm volatile(\n        \"ldrb r12, [%0, #1]\\n\"    // Load green.\n        \"lsls r12, r12, #24\\n\"    // Put green in MSB of color register.\n        \"ldrb r3, [%0, #0]\\n\"     // Load red.\n        \"lsls r3, r3, #16\\n\"\n        \"orrs r12, r12, r3\\n\"     // Put red in color register.\n        \"ldrb r3, [%0, #2]\\n\"     // Load blue.\n        \"lsls r3, r3, #8\\n\"\n        \"orrs r12, r12, r3\\n\"     // Put blue in LSB of color register.\n        \"rbit r12, r12\\n\"         // Reverse the bits so we can use right rotations.\n        \"adds  %0, %0, #3\\n\"      // Advance pointer to next color.\n\n        \"mov r3, #24\\n\"           // Initialize the loop counter register.\n\n        \"send_led_strip_bit%=:\\n\"\n        \"str %[val], %[set]\\n\"            // Drive the line high.\n        \"rrxs r12, r12\\n\"                 // Rotate right through carry.\n\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n\n        \"it cc\\n\" \"strcc %[val], %[clear]\\n\"  // If the bit to send is 0, set the line low now.\n\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n\n        \"it cs\\n\" \"strcs %[val], %[clear]\\n\"  // If the bit to send is 1, set the line low now.\n\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n        \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\" \"nop\\n\"\n\n        \"sub r3, r3, #1\\n\"                // Decrement the loop counter.\n        \"cbz r3, led_strip_asm_end%=\\n\"   // If we have sent 24 bits, go to the end.\n        \"b send_led_strip_bit%=\\n\"\n\n        \"led_strip_asm_end%=:\\n\"\n\n      : \"=r\" (colors)\n      : \"0\" (colors),\n        [set] \"m\" (port->PIO_SODR),\n        [clear] \"m\" (port->PIO_CODR),\n        [val] \"r\" (pinValue)\n      : \"r3\", \"r12\", \"cc\"\n      );\n\n      #endif\n\n      if (PololuLedStripBase::interruptFriendly)\n      {\n        // Experimentally on an AVR we found that one NOP is required after the SEI to actually let the\n        // interrupts fire.\n        __enable_irq();\n        asm volatile(\"nop\\n\");\n        __disable_irq();\n      }\n    }\n    __enable_irq();         // Re-enable interrupts now that we are done.\n    delayMicroseconds(80);  // Send the reset signal.\n  }\n\n}\n\nusing namespace Pololu;\n"
  },
  {
    "path": "README.md",
    "content": "# Arduino library for addressable RGB LED strips from Pololu\n\nVersion: 4.3.1<br>\nRelease date: 2021-01-12<br>\n[www.pololu.com](https://www.pololu.com/)\n\n[![Image](https://a.pololu-files.com/picture/0J4995.1200.jpg?e4ec28a3e9151b2e8f015c6cc6a4efab)](https://www.pololu.com/picture/view/0J4995)\n\n## Summary\n\nThis is a library for the Arduino for controlling these addressable\nRGB LED products from Pololu:\n\n* [Addressable RGB 30-LED Strip, 5V, 1m &#40;SK6812)](https://www.pololu.com/product/2526)\n* [Addressable RGB 60-LED Strip, 5V, 2m &#40;SK6812)](https://www.pololu.com/product/2527)\n* [Addressable RGB 150-LED Strip, 5V, 5m &#40;SK6812)](https://www.pololu.com/product/2528)\n* [Addressable RGB 60-LED Strip, 5V, 1m &#40;SK6812)](https://www.pololu.com/product/2529)\n* [Addressable RGB 120-LED Strip, 5V, 2m &#40;SK6812)](https://www.pololu.com/product/2530)\n* [Addressable High-Density RGB 72-LED Strip, 5V, 0.5m &#40;SK6812)](https://www.pololu.com/product/2531)\n* [Addressable RGB 30-LED Strip, 5V, 1m &#40;WS2812B)](https://www.pololu.com/product/2546)\n* [Addressable RGB 60-LED Strip, 5V, 2m &#40;WS2812B)](https://www.pololu.com/product/2547)\n* [Addressable RGB 150-LED Strip, 5V, 5m &#40;WS2812B)](https://www.pololu.com/product/2548)\n* [Addressable RGB 60-LED Strip, 5V, 1m &#40;WS2812B)](https://www.pololu.com/product/2549)\n* [Addressable RGB 120-LED Strip, 5V, 2m &#40;WS2812B)](https://www.pololu.com/product/2550)\n* [Addressable High-Density RGB 72-LED Strip, 5V, 0.5m &#40;WS2812B)](https://www.pololu.com/product/2551)\n* [Addressable Through-Hole 5mm RGB LED with Diffused Lens, WS2811 Driver (10-Pack)](https://www.pololu.com/product/2535)\n* [Addressable Through-Hole 8mm RGB LED with Diffused Lens, WS2811 Driver (10-Pack)](https://www.pololu.com/product/2536)\n* [Adafruit 16 WS2812 LED NeoPixel Ring](https://www.pololu.com/product/2537)\n* [Adafruit 24 WS2812 LED NeoPixel Ring](https://www.pololu.com/product/2538)\n* [Adafruit 15 WS2812 LED NeoPixel 1/4-Ring](https://www.pololu.com/product/2539)\n* [Adafruit 5&times;8 WS2812 LED NeoPixel Shield for Arduino](https://www.pololu.com/product/2772)\n* [Addressable RGB 30-LED Strip, 5V, 1m &#40;High-Speed TM1804)](https://www.pololu.com/product/2543)\n* [Addressable RGB 60-LED Strip, 5V, 2m &#40;High-Speed TM1804)](https://www.pololu.com/product/2544)\n* [Addressable RGB 150-LED Strip, 5V, 5m &#40;High-Speed TM1804)](https://www.pololu.com/product/2545)\n\nThis library is optimized for the SK6812 and WS2812B, so it transmits\ncolors in green-red-blue order.\n\nIf you have a WS2811 LED or a high-speed TM1804 LED strip, please note\nthat its red and green channels are swapped relative to the SK6812 and\nWS2812B, so you will need to swap those channels in your code. You\nmight prefer to use\n[version 2.1.0](https://github.com/pololu/pololu-led-strip-arduino/releases/tag/2.1.0)\nof the library, which does not require you to swap red and green in\nyour code.\n\nThis version of the library does not support the older low-speed\nTM1804 LED strips.  If you want to control those, we recommend using\n[version 1.2.0](https://github.com/pololu/pololu-led-strip-arduino/releases/tag/1.2.0),\nwhich runs slower but can work with any of the low-speed TM1804 LED\nstrips, high-speed TM1804 strips, SK6812 strips, WS2812B strips, or\nWS2811 LEDs.\n\nThis library allows complete control over the color of an arbitrary\nnumber of LED strips with an arbitrary number of LEDs.  Each LED can\nbe individually controlled, and LED strips can be chained together.\n\n## Supported platforms\n\nThis library and the examples are designed to work with the Arduino\nIDE versions 1.0 and 1.5 and probably will not work with earlier\nversions.\n\nThis library currently supports any board based on the ATmega168,\nATmega328P, ATmega328PB, ATmega32U4, or ATmega2560 which runs at\n8&nbsp;MHz, 12&nbsp;MHz, 16&nbsp;MHz, or 20&nbsp;MHz.\nThis includes the\n[A-Star boards](https://www.pololu.com/category/149/a-star-programmable-controllers),\nthe [Arduino Uno](https://www.pololu.com/catalog/product/2191),\nthe older Arduino Duemilanovae,\nthe [Baby Orangutan B-328](https://www.pololu.com/catalog/product/1220),\nthe [Orangutan SV-328](https://www.pololu.com/catalog/product/1227),\nthe [Arduino Leonardo](https://www.pololu.com/catalog/product/2192),\nthe [Arduino Micro](https://www.pololu.com/product/2188),\nand the [Arduino Mega](https://www.pololu.com/catalog/product/1699).\nNot all pins on the Arduino Mega are supported (see below).\n\nThis library also supports the\n[Arduino Due](https://www.pololu.com/catalog/product/2193), which is\nbased on the ATSAM3X8E.\n\n## Getting started\n\n### Hardware\n\nThe addressable RGB LED strips can be purchased on Pololu's website\nusing the links above.\n\nThe LED strip's input connector has two pins that should be connected\nto the Arduino.  The LED strip's ground will need to be connected to\none of the Arduino's GND pins, and the LED strip's signal input line\nwill be need to be connected to one of the Arduino's I/O lines.  Our\nexample sketches assume the signal line is connected to pin 12.  These\nconnections can be made using two\n[Male-Female Premium Jumper Wires](https://www.pololu.com/catalog/category/67),\nwith the female ends plugging into the LED strip.\n\nYou will also need to connect a suitable power supply to the LED strip\nusing one of the power connectors.  The power supply must be at the\nright voltage and provide enough current to meet the LED strip's\nrequirements.\n\n### Software\n\nIf you are using version 1.6.2 or later of the\n[Arduino software (IDE)](https://www.arduino.cc/en/Main/Software), you can use\nthe Library Manager to install this library:\n\n1. In the Arduino IDE, open the \"Sketch\" menu, select \"Include Library\", then\n   \"Manage Libraries...\".\n2. Search for \"PololuLedStrip\".\n3. Click the PololuLedStrip entry in the list.\n4. Click \"Install\".\n\nIf this does not work, you can manually install the library:\n\n1. Download the\n   [latest release archive from GitHub](https://github.com/pololu/pololu-led-strip-arduino/releases)\n   and decompress it.\n2. Rename the folder \"pololu-led-strip-arduino-xxxx\" to \"PololuLedStrip\".\n3. Drag the \"PololuLedStrip\" folder into the \"libraries\" directory inside your\n   Arduino sketchbook directory. You can view your sketchbook location by\n   opening the \"File\" menu and selecting \"Preferences\" in the Arduino IDE. If\n   there is not already a \"libraries\" folder in that location, you should make\n   the folder yourself.\n4. After installing the library, restart the Arduino IDE.\n\n## Examples\n\nSeveral example sketches are available that show how to use the\nlibrary. You can access them from the Arduino IDE by opening the\n\"File\" menu, selecting \"Examples\", and then selecting \"PololuLedStrip\". If\nyou cannot find these examples, the library was probably installed\nincorrectly and you should retry the installation instructions above.\n\n### LedStripGradient\n\nThis example code sketch lights up the LED strip with a moving\ngradient pattern.  You can open this example sketch by selecting\nFile->Examples->PololuLedStrip->LedStripGradient.  Click the \"Upload\"\nbutton to load it onto your board.\n\n### LedStripRainbow\n\nThis example is like LedStripGradient, but makes a rainbow pattern\ninstead.  You can open this example sketch by selecting\nFile->Examples->PololuLedStrip->LedStripRainbow.  Click the \"Upload\"\nbutton to load it onto your board.\n\n### LedStripColorTester\n\nThis example code sketch allows you to type colors into the Serial\nMonitor and see them on the LED strip.  You can open this example by\nselecting File->Examples->PololuLedStrip->LedStripColorTester.  Click\nthe \"Upload\" button to load it onto your board.  See the comments in\nthe code for more information on how to use it.\n\n## Timing details\n\nThis library takes about 1.1 ms to update 30 LEDs (1 meter).  The LED\nstrips use a high speed one-wire protocol with relatively strict\ntiming requirements, so this library disables interrupts to ensure\nreliable color transmission.  Unfortunately, disabling the interrupts\ncauses problems in other libraries that uses interrupts, such as the\n`Serial` library and the functions like `millis()` that keep track of\ntime.\n\nThis library provides an `interruptFriendly` option that can let it\ncoexist with interrupt-based libraries.  When this option is enabled,\nthe library will temporarily enable interrupts after each color is\nsent, about every 36 microseconds.  If you can keep all of your\ninterrupts short enough, then this option should allow this library to\nwork in conjunction with your interrupt-based libraries.  However, if\nyou have an interrupt enabled that takes longer than about 38\nmicroseconds for the SK6812, 5 microseconds for the WS2812B, or 8\nmicroseconds for the TM1804, then this interrupt will sometimes cause\nan extra long low pulse to emitted, which will be interpreted by the\nLED strip as a reset command.  This can cause visible flickering in\nthe LED strip.  By default, many common Arduinos such as the Arduino\nUno have an interrupt that runs every millisecond and takes longer\nthan 8 microseconds.  To turn on the `interruptFriendly` option,\nadd this line to your `setup()` function:\n\n```c++\nPololuLedStripBase::interruptFriendly = true;\n```\n\nBecause the library disables interrupts by default, it can cause the\ntimekeeping functions of your Arduino to miss ticks.  As a result, the\nArduino's time, which can be accessed from functions like `millis()`,\nwill appear to be running slower than usual.  In our demo code, we get\naround this by adding a 10 millisecond delay at the end of the `loop`\nfunction; this ensures that the Arduino will only spend a minority of\nits time updating the LED strip and therefore limits how much the\ntimekeeping will be affected.\n\n## Documentation\n\n### rgb_color\n\nThe library defines a type named `rgb_color` which can be used to\nrepresent colors.  The type is defined like this:\n\n```c++\ntypedef struct rgb_color\n{\n  unsigned char red, green, blue;\n} rgb_color;\n```\n\nThe fields `red`, `green`, and `blue` are numbers between 0 and 255\nand represent the brightness of the red, green, and blue color\ncomponents respectively.\n\n### PololuLedStrip&lt;pin&gt;\n\nThe libary defines a template class named `PololuLedStrip<pin>`.  The\n`pin` template parameter is an `unsigned char` and should be the\nnumber of the Arduino pin that the LED strip's data input line is\nconnected to.  For ATmega2560-based boards such as the Arduino Mega,\nonly the following pins are usable: 0&ndash;5, 10&ndash;13,\n18&ndash;41, and 50&ndash;61 (ports A through G).  This template class\ninherits from the abstract class `PololuLedStripBase`, which is useful\nif you want to have pointers to LED strip objects.\n\nThis class has no constructor except the default one.  This class has\none function:\n\n- `void write(rgb_color * colors, unsigned int count)` <br> Writes the\n  specified colors to the LED strip.  The `colors` parameter should be\n  a pointer to an array of `rgb_color` structs in RAM.  The `count`\n  parameter is the number of colors to write.  The first color in the\n  array will be written to the LED closest to the data input\n  connector.  To update all the LEDs in the LED strip, `count` should\n  be equal to or greater than the number of LEDs in the strip.  If\n  `count` is less than the number of LEDs in the strip, then some LEDs\n  near the end of the strip will not be updated.  This function\n  disables interrupts temporarily.  This function pauses for over 10\n  us at the end before returning to allow the colors to take effect.\n\n### PololuLedStripBase\n\n- `static bool interruptFriendly;` <br> This option defaults to\n  `false`.  Setting this to `true` changes the behavior of the `write`\n  function, making it enable interrupts after each color is sent,\n  about every 36 microseconds.  See the discussion above.\n\n## Chaining LED strips together\n\nNo special code is required to chain LED strips together.  An X-meter\nLED strip chained to a Y-meter LED strip can be controlled in exactly\nthe same way as a single (X+Y)-meter LED strip.\n\n## Version history\n\n* 4.3.1 (2021-01-12): Changed the `architectures` field in `library.properties` from `*` to `avr,sam`.\n* 4.3.0 (2019-04-03): Added support for the ATmega328PB and 12 MHz AVRs.\n* 4.2.0 (2017-03-20): Added a constructor for rgb_color that takes the three color values and changed the examples to use it.  Added `keywords.txt`, which is used by the Arduino IDE for syntax highlighting.\n* 4.1.1 (2017-01-16): Fixed library.properties \"url\" field.\n* 4.1.0 (2016-11-03): Changed the reset time from 50&nbsp;&mu;s to 80&nbsp;&mu;s to support the SK6812.\n* 4.0.0 (2016-08-22): Updated library to work with the Arduino Library Manager.\n* 3.2.0 (2014-08-27): Added support for AVRs running at 8 MHz (thanks odewdney).\n* 3.1.2 (2014-06-10): Fixed a bug in the HSV-to-RGB conversion in the LedStripRainbow example.\n* 3.1.1 (2014-01-07): Changed the examples to use `uint16_t` instead of `byte` for `i`, making it easier to expand them beyond 254 LEDs.\n* 3.1.0 (2013-12-19): Added the LedStripXmas example.\n* 3.0.0 (2013-11-20): Switched the red and the green channels and increased the reset time so that this library will work nicely with the new WS2812 and WS2182B LED strips.  The high-speed TM1804 LED strips still work if you switch red and green in your code.\n* 2.1.0 (2013-11-11): Added the LedStripRainbow example.\n* 2.0.0 (2013-10-07): Dropped support for the older, slower LED strips in order to make the library faster.\n* 1.2.0 (2013-10-07): Changed the timing so that this library will work the new high-speed strips but also keep working with the old low-speed strips.\n* 1.1.0 (2012-12-17): Added support for ATmega32U4-based boards such as the Arduino Leonardo.  Added support for ARM-based boards such as the Arduino Due.\n* 1.0.0 (2012-03-09): Original release.\n"
  },
  {
    "path": "examples/LedStripColorTester/LedStripColorTester.ino",
    "content": "/* LedStripColorTester: Example Arduino sketch that lets you\n * type in a color on a PC and see it on the LED strip.\n *\n * To use this, you will need to plug an Addressable RGB LED\n * strip from Pololu into pin 12.  After uploading the sketch,\n * select \"Serial Monitor\" from the \"Tools\" menu.  In the input\n * box, type a color and press enter.\n *\n * The format of the color should be \"R,G,B!\" where R, G, and B\n * are numbers between 0 and 255 representing the brightnesses\n * of the red, green, and blue components respectively.\n *\n * For example, to get green, you could type:\n *   40,100,0!\n *\n * You can leave off the exclamation point if you change the\n * Serial Monitor's line ending setting to be \"Newline\" instead\n * of \"No line ending\".\n *\n * Please note that this sketch only transmits colors to the\n * LED strip after it receives them from the computer, so if\n * the LED strip loses power it will be off until you resend\n * the color.\n */\n\n#include <PololuLedStrip.h>\n\n// Create an ledStrip object and specify the pin it will use.\nPololuLedStrip<12> ledStrip;\n\n// Create a buffer for holding the colors (3 bytes per color).\n#define LED_COUNT 60\nrgb_color colors[LED_COUNT];\n\nvoid setup()\n{\n  // Start up the serial port, for communication with the PC.\n  Serial.begin(115200);\n  Serial.println(\"Ready to receive colors.\");\n}\n\nvoid loop()\n{\n  // If any digit is received, we will go into integer parsing mode\n  // until all three calls to parseInt return an interger or time out.\n  if (Serial.available())\n  {\n    char c = Serial.peek();\n    if (!(c >= '0' && c <= '9'))\n    {\n      Serial.read(); // Discard non-digit character\n    }\n    else\n    {\n      // Read the color from the computer.\n      rgb_color color;\n      color.red = Serial.parseInt();\n      color.green = Serial.parseInt();\n      color.blue = Serial.parseInt();\n\n      // Update the colors buffer.\n      for(uint16_t i = 0; i < LED_COUNT; i++)\n      {\n        colors[i] = color;\n      }\n\n      // Write to the LED strip.\n      ledStrip.write(colors, LED_COUNT);\n\n      Serial.print(\"Showing color: \");\n      Serial.print(color.red);\n      Serial.print(\",\");\n      Serial.print(color.green);\n      Serial.print(\",\");\n      Serial.println(color.blue);\n    }\n  }\n}\n"
  },
  {
    "path": "examples/LedStripGradient/LedStripGradient.ino",
    "content": "/* LedStripGradient: Example Arduino sketch that shows\n * how to control an Addressable RGB LED Strip from Pololu.\n *\n * To use this, you will need to plug an Addressable RGB LED\n * strip from Pololu into pin 12.  After uploading the sketch,\n * you should see a pattern on the LED strip that fades from\n * green to pink and also moves along the strip.\n */\n\n#include <PololuLedStrip.h>\n\n// Create an ledStrip object and specify the pin it will use.\nPololuLedStrip<12> ledStrip;\n\n// Create a buffer for holding the colors (3 bytes per color).\n#define LED_COUNT 60\nrgb_color colors[LED_COUNT];\n\nvoid setup()\n{\n}\n\nvoid loop()\n{\n  // Update the colors.\n  byte time = millis() >> 2;\n  for (uint16_t i = 0; i < LED_COUNT; i++)\n  {\n    byte x = time - 8*i;\n    colors[i] = rgb_color(x, 255 - x, x);\n  }\n\n  // Write the colors to the LED strip.\n  ledStrip.write(colors, LED_COUNT);\n\n  delay(10);\n}\n"
  },
  {
    "path": "examples/LedStripRainbow/LedStripRainbow.ino",
    "content": "/* LedStripRainbow: Example Arduino sketch that shows\n * how to make a moving rainbow pattern on an\n * Addressable RGB LED Strip from Pololu.\n *\n * To use this, you will need to plug an Addressable RGB LED\n * strip from Pololu into pin 12.  After uploading the sketch,\n * you should see a moving rainbow.\n */\n\n#include <PololuLedStrip.h>\n\n// Create an ledStrip object and specify the pin it will use.\nPololuLedStrip<12> ledStrip;\n\n// Create a buffer for holding the colors (3 bytes per color).\n#define LED_COUNT 60\nrgb_color colors[LED_COUNT];\n\nvoid setup()\n{\n}\n\n// Converts a color from HSV to RGB.\n// h is hue, as a number between 0 and 360.\n// s is the saturation, as a number between 0 and 255.\n// v is the value, as a number between 0 and 255.\nrgb_color hsvToRgb(uint16_t h, uint8_t s, uint8_t v)\n{\n    uint8_t f = (h % 60) * 255 / 60;\n    uint8_t p = (255 - s) * (uint16_t)v / 255;\n    uint8_t q = (255 - f * (uint16_t)s / 255) * (uint16_t)v / 255;\n    uint8_t t = (255 - (255 - f) * (uint16_t)s / 255) * (uint16_t)v / 255;\n    uint8_t r = 0, g = 0, b = 0;\n    switch((h / 60) % 6){\n        case 0: r = v; g = t; b = p; break;\n        case 1: r = q; g = v; b = p; break;\n        case 2: r = p; g = v; b = t; break;\n        case 3: r = p; g = q; b = v; break;\n        case 4: r = t; g = p; b = v; break;\n        case 5: r = v; g = p; b = q; break;\n    }\n    return rgb_color(r, g, b);\n}\n\nvoid loop()\n{\n  // Update the colors.\n  uint16_t time = millis() >> 2;\n  for(uint16_t i = 0; i < LED_COUNT; i++)\n  {\n    byte x = (time >> 2) - (i << 3);\n    colors[i] = hsvToRgb((uint32_t)x * 359 / 256, 255, 255);\n  }\n\n  // Write the colors to the LED strip.\n  ledStrip.write(colors, LED_COUNT);\n\n  delay(10);\n}\n"
  },
  {
    "path": "examples/LedStripXmas/LedStripXmas.ino",
    "content": "/* LedStripXmas: A series of fun patterns for use with LED\n * strips set up as a Christmas lighting display.  You can see an\n * earlier version of this code running in this youtube video:\n * http://www.youtube.com/watch?v=VZRN0UrQSlc\n * To use this, you will need to plug the signal wire of an\n * Addressable RGB LED strip from Pololu into pin 12.\n *\n * You can optionally connect a switch between pin 3 and ground\n * to control if the Arduino automatically cycles through the\n * different patterns.  When no switch is present or the switch\n * is open, the patterns will cycle.\n * \n * You can also optionally connect a button between pin 2 and\n * ground that displays the next pattern in the series each time\n * it is pushed.  This example requires the PololuLEDStrip\n * library to be installed.\n *\n * NOTE: Timing is determined entirely by a counter incremented\n * by the main loop, and the execution time of the main loop is\n * dominated by the time it takes to write the LED colors array\n * to the LED strips.  Changing LED_COUNT will change the\n * timing, so if you like the default timing and you have fewer\n * than 509 LEDs, you might want to add an appropriate delay to\n * the main loop.  Timing is not done with the Arduino's system\n * timer because that does not work properly when this program\n * is running (the interrupts that maintain the system time must\n * be disabled while the LED strips are being updated or else\n * they will cause glitches on the LEDs).\n */\n\n#ifdef __AVR__\n#define HAS_EEPROM\n#endif\n\n#include <PololuLedStrip.h>\n\n#ifdef HAS_EEPROM\n#include <EEPROM.h>\n#endif\n\n// Create an ledStrip object on pin 12.\n#define LED_SIGNAL_PIN 12\nPololuLedStrip<LED_SIGNAL_PIN> ledStrip;\n\n#define NEXT_PATTERN_BUTTON_PIN  2  // button between this pin and ground\n#define AUTOCYCLE_SWITCH_PIN  3  // switch between this pin and ground\n\n// Create a buffer for holding 509 colors.\n// This takes 1527 bytes and uses up most of the 2KB RAM on an Uno,\n// so we should be very sparing with additional RAM use and keep\n// an eye out for possible stack overflow problems.\n#define LED_COUNT 509\nrgb_color colors[LED_COUNT];\n\n#define NUM_STATES  7  // number of patterns to cycle through\n\n// system timer, incremented by one every time through the main loop\nunsigned int loopCount = 0;\n\nunsigned int seed = 0;  // used to initialize random number generator\n\n// enumerate the possible patterns in the order they will cycle\nenum Pattern {\n  WarmWhiteShimmer = 0,\n  RandomColorWalk = 1,\n  TraditionalColors = 2,\n  ColorExplosion = 3,\n  Gradient = 4,\n  BrightTwinkle = 5,\n  Collision = 6,\n  AllOff = 255\n};\nunsigned char pattern = AllOff;\nunsigned int maxLoops;  // go to next state when loopCount >= maxLoops\n\n\n// initialization stuff\nvoid setup()\n{\n  // initialize the random number generator with a seed obtained by\n  // summing the voltages on the disconnected analog inputs\n  for (int i = 0; i < 8; i++)\n  {\n    seed += analogRead(i);\n  }\n  #ifdef HAS_EEPROM\n    seed += EEPROM.read(0);  // get part of the seed from EEPROM\n  #endif\n  randomSeed(seed);\n\n  #ifdef HAS_EEPROM\n    // save a random number in EEPROM to be used for random seed\n    // generation the next time the program runs\n    EEPROM.write(0, random(256));\n  #endif\n\n  // optionally connect a switch between this pin and ground\n  // when the input is low, freeze the cycle at the current pattern\n  pinMode(AUTOCYCLE_SWITCH_PIN, INPUT_PULLUP);\n  \n  // optionally connect a button between this pin and ground\n  // when the input goes low, advance to the next pattern in cycle\n  pinMode(NEXT_PATTERN_BUTTON_PIN, INPUT_PULLUP);\n  \n  delay(10);  // give pull-ups time raise the input voltage\n}\n\n\n// main loop\nvoid loop()\n{\n  handleNextPatternButton();\n  \n  if (loopCount == 0)\n  {\n    // whenever timer resets, clear the LED colors array (all off)\n    for (int i = 0; i < LED_COUNT; i++)\n    {\n      colors[i] = rgb_color(0, 0, 0);\n    }\n  }\n  \n  if (pattern == WarmWhiteShimmer || pattern == RandomColorWalk)\n  {\n    // for these two patterns, we want to make sure we get the same\n    // random sequence six times in a row (this provides smoother\n    // random fluctuations in brightness/color)\n    if (loopCount % 6 == 0)\n    {\n      seed = random(30000);\n    }\n    randomSeed(seed);\n  }\n  \n  // call the appropriate pattern routine based on state; these\n  // routines just set the colors in the colors array\n  switch (pattern)\n  {\n    case WarmWhiteShimmer:\n      // warm white shimmer for 300 loopCounts, fading over last 70\n      maxLoops = 300;\n      warmWhiteShimmer(loopCount > maxLoops - 70);\n      break;\n      \n    case RandomColorWalk:\n      // start with alternating red and green colors that randomly walk\n      // to other colors for 400 loopCounts, fading over last 80\n      maxLoops = 400;\n      randomColorWalk(loopCount == 0 ? 1 : 0, loopCount > maxLoops - 80);\n      break;\n      \n    case TraditionalColors:\n      // repeating pattern of red, green, orange, blue, magenta that\n      // slowly moves for 400 loopCounts\n      maxLoops = 400;\n      traditionalColors();\n      break;\n      \n    case ColorExplosion:\n      // bursts of random color that radiate outwards from random points\n      // for 630 loop counts; no burst generation for the last 70 counts\n      // of every 200 count cycle or over the over final 100 counts\n      // (this creates a repeating bloom/decay effect)\n      maxLoops = 630;\n      colorExplosion((loopCount % 200 > 130) || (loopCount > maxLoops - 100));\n      break;\n      \n    case Gradient:\n      // red -> white -> green -> white -> red ... gradiant that scrolls\n      // across the strips for 250 counts; this pattern is overlaid with\n      // waves of dimness that also scroll (at twice the speed)\n      maxLoops = 250;\n      gradient();\n      delay(6);  // add an extra 6ms delay to slow things down\n      break;\n      \n    case BrightTwinkle:\n      // random LEDs light up brightly and fade away; it is a very similar\n      // algorithm to colorExplosion (just no radiating outward from the\n      // LEDs that light up); as time goes on, allow progressively more\n      // colors, halting generation of new twinkles for last 100 counts.\n      maxLoops = 1200;\n      if (loopCount < 400)\n      {\n        brightTwinkle(0, 1, 0);  // only white for first 400 loopCounts\n      }\n      else if (loopCount < 650)\n      {\n        brightTwinkle(0, 2, 0);  // white and red for next 250 counts\n      }\n      else if (loopCount < 900)\n      {\n        brightTwinkle(1, 2, 0);  // red, and green for next 250 counts\n      }\n      else\n      {\n        // red, green, blue, cyan, magenta, yellow for the rest of the time\n        brightTwinkle(1, 6, loopCount > maxLoops - 100);\n      }\n      break;\n      \n    case Collision:\n      // colors grow towards each other from the two ends of the strips,\n      // accelerating until they collide and the whole strip flashes\n      // white and fades; this repeats until the function indicates it\n      // is done by returning 1, at which point we stop keeping maxLoops\n      // just ahead of loopCount\n      if (!collision())\n      {\n        maxLoops = loopCount + 2;\n      }\n      break;\n  } \n\n  // update the LED strips with the colors in the colors array\n  ledStrip.write(colors, LED_COUNT);\n  loopCount++;  // increment our loop counter/timer.\n\n  if (loopCount >= maxLoops && digitalRead(AUTOCYCLE_SWITCH_PIN))\n  {\n    // if the time is up for the current pattern and the optional hold\n    // switch is not grounding the AUTOCYCLE_SWITCH_PIN, clear the\n    // loop counter and advance to the next pattern in the cycle\n    loopCount = 0;  // reset timer\n    pattern = ((unsigned char)(pattern+1))%NUM_STATES;  // advance to next pattern\n  }\n}\n\n\n// This function detects if the optional next pattern button is pressed\n// (connecting the pin to ground) and advances to the next pattern\n// in the cycle if so.  It also debounces the button.\nvoid handleNextPatternButton()\n{\n  if (digitalRead(NEXT_PATTERN_BUTTON_PIN) == 0)\n  {\n    // if optional button is pressed\n    while (digitalRead(NEXT_PATTERN_BUTTON_PIN) == 0)\n    {\n      // wait for button to be released\n      while (digitalRead(NEXT_PATTERN_BUTTON_PIN) == 0);\n      delay(10);  // debounce the button\n    }\n    loopCount = 0;  // reset timer\n    pattern = ((unsigned char)(pattern+1))%NUM_STATES;  // advance to next pattern\n  }\n}\n\n\n// This function applies a random walk to val by increasing or\n// decreasing it by changeAmount or by leaving it unchanged.\n// val is a pointer to the byte to be randomly changed.\n// The new value of val will always be within [0, maxVal].\n// A walk direction of 0 decreases val and a walk direction of 1\n// increases val.  The directions argument specifies the number of\n// possible walk directions to choose from, so when directions is 1, val\n// will always decrease; when directions is 2, val will have a 50% chance\n// of increasing and a 50% chance of decreasing; when directions is 3,\n// val has an equal chance of increasing, decreasing, or staying the same.\nvoid randomWalk(unsigned char *val, unsigned char maxVal, unsigned char changeAmount, unsigned char directions)\n{\n  unsigned char walk = random(directions);  // direction of random walk\n  if (walk == 0)\n  {\n    // decrease val by changeAmount down to a min of 0\n    if (*val >= changeAmount)\n    {\n      *val -= changeAmount;\n    }\n    else\n    {\n      *val = 0;\n    }\n  }\n  else if (walk == 1)\n  {\n    // increase val by changeAmount up to a max of maxVal\n    if (*val <= maxVal - changeAmount)\n    {\n      *val += changeAmount;\n    }\n    else\n    {\n      *val = maxVal;\n    }\n  }\n}\n\n\n// This function fades val by decreasing it by an amount proportional\n// to its current value.  The fadeTime argument determines the\n// how quickly the value fades.  The new value of val will be:\n//   val = val - val*2^(-fadeTime)\n// So a smaller fadeTime value leads to a quicker fade.\n// If val is greater than zero, val will always be decreased by\n// at least 1.\n// val is a pointer to the byte to be faded.\nvoid fade(unsigned char *val, unsigned char fadeTime)\n{\n  if (*val != 0)\n  {\n    unsigned char subAmt = *val >> fadeTime;  // val * 2^-fadeTime\n    if (subAmt < 1)\n      subAmt = 1;  // make sure we always decrease by at least 1\n    *val -= subAmt;  // decrease value of byte pointed to by val\n  }\n}\n\n\n// ***** PATTERN WarmWhiteShimmer *****\n// This function randomly increases or decreases the brightness of the \n// even red LEDs by changeAmount, capped at maxBrightness.  The green\n// and blue LED values are set proportional to the red value so that\n// the LED color is warm white.  Each odd LED is set to a quarter the\n// brightness of the preceding even LEDs.  The dimOnly argument\n// disables the random increase option when it is true, causing\n// all the LEDs to get dimmer by changeAmount; this can be used for a\n// fade-out effect.\nvoid warmWhiteShimmer(unsigned char dimOnly)\n{\n  const unsigned char maxBrightness = 120;  // cap on LED brighness\n  const unsigned char changeAmount = 2;   // size of random walk step\n\n  for (int i = 0; i < LED_COUNT; i += 2)\n  {\n    // randomly walk the brightness of every even LED\n    randomWalk(&colors[i].red, maxBrightness, changeAmount, dimOnly ? 1 : 2);\n    \n    // warm white: red = x, green = 0.8x, blue = 0.125x\n    colors[i].green = colors[i].red*4/5;  // green = 80% of red\n    colors[i].blue = colors[i].red >> 3;  // blue = red/8\n    \n    // every odd LED gets set to a quarter the brighness of the preceding even LED\n    if (i + 1 < LED_COUNT)\n    {\n      colors[i+1] = rgb_color(colors[i].red >> 2, colors[i].green >> 2, colors[i].blue >> 2);\n    }\n  }\n}\n\n\n// ***** PATTERN RandomColorWalk *****\n// This function randomly changes the color of every seventh LED by\n// randomly increasing or decreasing the red, green, and blue components\n// by changeAmount (capped at maxBrightness) or leaving them unchanged.\n// The two preceding and following LEDs are set to progressively dimmer\n// versions of the central color.  The initializeColors argument\n// determines how the colors are initialized:\n//   0: randomly walk the existing colors\n//   1: set the LEDs to alternating red and green segments\n//   2: set the LEDs to random colors\n// When true, the dimOnly argument changes the random walk into a 100%\n// chance of LEDs getting dimmer by changeAmount; this can be used for\n// a fade-out effect.\nvoid randomColorWalk(unsigned char initializeColors, unsigned char dimOnly)\n{\n  const unsigned char maxBrightness = 180;  // cap on LED brightness\n  const unsigned char changeAmount = 3;  // size of random walk step\n  \n  // pick a good starting point for our pattern so the entire strip\n  // is lit well (if we pick wrong, the last four LEDs could be off)\n  unsigned char start;\n  switch (LED_COUNT % 7)\n  {\n    case 0:\n      start = 3;\n      break;\n    case 1:\n      start = 0;\n      break;\n    case 2:\n      start = 1;\n      break;\n    default:\n      start = 2;\n  }\n\n  for (int i = start; i < LED_COUNT; i+=7)\n  {\n    if (initializeColors == 0)\n    {\n      // randomly walk existing colors of every seventh LED\n      // (neighboring LEDs to these will be dimmer versions of the same color)\n      randomWalk(&colors[i].red, maxBrightness, changeAmount, dimOnly ? 1 : 3);\n      randomWalk(&colors[i].green, maxBrightness, changeAmount, dimOnly ? 1 : 3);\n      randomWalk(&colors[i].blue, maxBrightness, changeAmount, dimOnly ? 1 : 3);\n    }\n    else if (initializeColors == 1)\n    {\n      // initialize LEDs to alternating red and green\n      if (i % 2)\n      {\n        colors[i] = rgb_color(maxBrightness, 0, 0);\n      }\n      else\n      {\n        colors[i] = rgb_color(0, maxBrightness, 0);\n      }\n    }\n    else\n    {\n      // initialize LEDs to a string of random colors\n      colors[i] = rgb_color(random(maxBrightness), random(maxBrightness), random(maxBrightness));\n    }\n    \n    // set neighboring LEDs to be progressively dimmer versions of the color we just set\n    if (i >= 1)\n    {\n      colors[i-1] = rgb_color(colors[i].red >> 2, colors[i].green >> 2, colors[i].blue >> 2);\n    }\n    if (i >= 2)\n    {\n      colors[i-2] = rgb_color(colors[i].red >> 3, colors[i].green >> 3, colors[i].blue >> 3);\n    }\n    if (i + 1 < LED_COUNT)\n    {\n      colors[i+1] = colors[i-1];\n    }\n    if (i + 2 < LED_COUNT)\n    {\n      colors[i+2] = colors[i-2];\n    }\n  }\n}\n\n\n// ***** PATTERN TraditionalColors *****\n// This function creates a repeating patern of traditional Christmas\n// light colors: red, green, orange, blue, magenta.\n// Every fourth LED is colored, and the pattern slowly moves by fading\n// out the current set of lit LEDs while gradually brightening a new\n// set shifted over one LED.\nvoid traditionalColors()\n{\n  // loop counts to leave strip initially dark\n  const unsigned char initialDarkCycles = 10;\n  // loop counts it takes to go from full off to fully bright\n  const unsigned char brighteningCycles = 20;\n  \n  if (loopCount < initialDarkCycles)  // leave strip fully off for 20 cycles\n  {\n    return;\n  }\n\n  // if LED_COUNT is not an exact multiple of our repeating pattern size,\n  // it will not wrap around properly, so we pick the closest LED count\n  // that is an exact multiple of the pattern period (20) and is not smaller\n  // than the actual LED count.\n  unsigned int extendedLEDCount = (((LED_COUNT-1)/20)+1)*20;\n\n  for (int i = 0; i < extendedLEDCount; i++)\n  {\n    unsigned char brightness = (loopCount - initialDarkCycles)%brighteningCycles + 1;\n    unsigned char cycle = (loopCount - initialDarkCycles)/brighteningCycles;\n\n    // transform i into a moving idx space that translates one step per\n    // brightening cycle and wraps around\n    unsigned int idx = (i + cycle)%extendedLEDCount;\n    if (idx < LED_COUNT)  // if our transformed index exists\n    {\n      if (i % 4 == 0)\n      {\n        // if this is an LED that we are coloring, set the color based\n        // on the LED and the brightness based on where we are in the\n        // brightening cycle\n        switch ((i/4)%5)\n        {\n           case 0:  // red\n             colors[idx].red = 200 * brightness/brighteningCycles; \n             colors[idx].green = 10 * brightness/brighteningCycles; \n             colors[idx].blue = 10 * brightness/brighteningCycles;  \n             break;\n           case 1:  // green\n             colors[idx].red = 10 * brightness/brighteningCycles; \n             colors[idx].green = 200 * brightness/brighteningCycles;  \n             colors[idx].blue = 10 * brightness/brighteningCycles; \n             break;\n           case 2:  // orange\n             colors[idx].red = 200 * brightness/brighteningCycles;  \n             colors[idx].green = 120 * brightness/brighteningCycles; \n             colors[idx].blue = 0 * brightness/brighteningCycles; \n             break;\n           case 3:  // blue\n             colors[idx].red = 10 * brightness/brighteningCycles; \n             colors[idx].green = 10 * brightness/brighteningCycles; \n             colors[idx].blue = 200 * brightness/brighteningCycles; \n             break;\n           case 4:  // magenta\n             colors[idx].red = 200 * brightness/brighteningCycles; \n             colors[idx].green = 64 * brightness/brighteningCycles;  \n             colors[idx].blue = 145 * brightness/brighteningCycles;  \n             break;\n        }\n      }\n      else\n      {\n        // fade the 3/4 of LEDs that we are not currently brightening\n        fade(&colors[idx].red, 3);\n        fade(&colors[idx].green, 3);\n        fade(&colors[idx].blue, 3);\n      }\n    }\n  }\n}\n\n\n// Helper function for adjusting the colors for the BrightTwinkle\n// and ColorExplosion patterns.  Odd colors get brighter and even\n// colors get dimmer.\nvoid brightTwinkleColorAdjust(unsigned char *color)\n{\n  if (*color == 255)\n  {\n    // if reached max brightness, set to an even value to start fade\n    *color = 254;\n  }\n  else if (*color % 2)\n  {\n    // if odd, approximately double the brightness\n    // you should only use odd values that are of the form 2^n-1,\n    // which then gets a new value of 2^(n+1)-1\n    // using other odd values will break things\n    *color = *color * 2 + 1;\n  }\n  else if (*color > 0)\n  {\n    fade(color, 4);\n    if (*color % 2)\n    {\n      (*color)--;  // if faded color is odd, subtract one to keep it even\n    }\n  }\n}\n\n\n// Helper function for adjusting the colors for the ColorExplosion\n// pattern.  Odd colors get brighter and even colors get dimmer.\n// The propChance argument determines the likelihood that neighboring\n// LEDs are put into the brightening stage when the central LED color\n// is 31 (chance is: 1 - 1/(propChance+1)).  The neighboring LED colors\n// are pointed to by leftColor and rightColor (it is not important that\n// the leftColor LED actually be on the \"left\" in your setup).\nvoid colorExplosionColorAdjust(unsigned char *color, unsigned char propChance,\n unsigned char *leftColor, unsigned char *rightColor)\n{\n  if (*color == 31 && random(propChance+1) != 0)\n  {\n    if (leftColor != 0 && *leftColor == 0)\n    {\n      *leftColor = 1;  // if left LED exists and color is zero, propagate\n    }\n    if (rightColor != 0 && *rightColor == 0)\n    {\n      *rightColor = 1;  // if right LED exists and color is zero, propagate\n    }\n  }\n  brightTwinkleColorAdjust(color);\n}\n\n\n// ***** PATTERN ColorExplosion *****\n// This function creates bursts of expanding, overlapping colors by\n// randomly picking LEDs to brighten and then fade away.  As these LEDs\n// brighten, they have a chance to trigger the same process in\n// neighboring LEDs.  The color of the burst is randomly chosen from\n// among red, green, blue, and white.  If a red burst meets a green\n// burst, for example, the overlapping portion will be a shade of yellow\n// or orange.\n// When true, the noNewBursts argument changes prevents the generation\n// of new bursts; this can be used for a fade-out effect.\n// This function uses a very similar algorithm to the BrightTwinkle\n// pattern.  The main difference is that the random twinkling LEDs of\n// the BrightTwinkle pattern do not propagate to neighboring LEDs.\nvoid colorExplosion(unsigned char noNewBursts)\n{\n  // adjust the colors of the first LED\n  colorExplosionColorAdjust(&colors[0].red, 9, (unsigned char*)0, &colors[1].red);\n  colorExplosionColorAdjust(&colors[0].green, 9, (unsigned char*)0, &colors[1].green);\n  colorExplosionColorAdjust(&colors[0].blue, 9, (unsigned char*)0, &colors[1].blue);\n\n  for (int i = 1; i < LED_COUNT - 1; i++)\n  {\n    // adjust the colors of second through second-to-last LEDs\n    colorExplosionColorAdjust(&colors[i].red, 9, &colors[i-1].red, &colors[i+1].red);\n    colorExplosionColorAdjust(&colors[i].green, 9, &colors[i-1].green, &colors[i+1].green);\n    colorExplosionColorAdjust(&colors[i].blue, 9, &colors[i-1].blue, &colors[i+1].blue);\n  }\n  \n  // adjust the colors of the last LED\n  colorExplosionColorAdjust(&colors[LED_COUNT-1].red, 9, &colors[LED_COUNT-2].red, (unsigned char*)0);\n  colorExplosionColorAdjust(&colors[LED_COUNT-1].green, 9, &colors[LED_COUNT-2].green, (unsigned char*)0);\n  colorExplosionColorAdjust(&colors[LED_COUNT-1].blue, 9, &colors[LED_COUNT-2].blue, (unsigned char*)0);\n\n  if (!noNewBursts)\n  {\n    // if we are generating new bursts, randomly pick one new LED\n    // to light up\n    for (int i = 0; i < 1; i++)\n    {\n      int j = random(LED_COUNT);  // randomly pick an LED\n\n      switch(random(7))  // randomly pick a color\n      {\n        // 2/7 chance we will spawn a red burst here (if LED has no red component)\n        case 0:\n        case 1:\n          if (colors[j].red == 0)\n          {\n            colors[j].red = 1;\n          }\n          break;\n        \n        // 2/7 chance we will spawn a green burst here (if LED has no green component)\n        case 2:\n        case 3:\n          if (colors[j].green == 0)\n          {\n            colors[j].green = 1;\n          }\n          break;\n\n        // 2/7 chance we will spawn a white burst here (if LED is all off)\n        case 4:\n        case 5:\n          if ((colors[j].red == 0) && (colors[j].green == 0) && (colors[j].blue == 0))\n          {\n            colors[j] = rgb_color(1, 1, 1);\n          }\n          break;\n        \n        // 1/7 chance we will spawn a blue burst here (if LED has no blue component)\n        case 6:\n          if (colors[j].blue == 0)\n          {\n            colors[j].blue = 1;\n          }\n          break;\n          \n        default:\n          break;\n      }\n    }\n  }\n}\n\n\n// ***** PATTERN Gradient *****\n// This function creates a scrolling color gradient that smoothly\n// transforms from red to white to green back to white back to red.\n// This pattern is overlaid with waves of brightness and dimness that\n// scroll at twice the speed of the color gradient.\nvoid gradient()\n{\n  unsigned int j = 0;\n  \n  // populate colors array with full-brightness gradient colors\n  // (since the array indices are a function of loopCount, the gradient\n  // colors scroll over time)\n  while (j < LED_COUNT)\n  {\n    // transition from red to green over 8 LEDs\n    for (int i = 0; i < 8; i++)\n    {\n      if (j >= LED_COUNT){ break; }\n      colors[(loopCount/2 + j + LED_COUNT)%LED_COUNT] = rgb_color(160 - 20*i, 20*i, (160 - 20*i)*20*i/160);\n      j++;\n    }\n    // transition from green to red over 8 LEDs\n    for (int i = 0; i < 8; i++)\n    {\n      if (j >= LED_COUNT){ break; }\n      colors[(loopCount/2 + j + LED_COUNT)%LED_COUNT] = rgb_color(20*i, 160 - 20*i, (160 - 20*i)*20*i/160);\n      j++;\n    }\n  }\n  \n  // modify the colors array to overlay the waves of dimness\n  // (since the array indices are a function of loopCount, the waves\n  // of dimness scroll over time)\n  const unsigned char fullDarkLEDs = 10;  // number of LEDs to leave fully off\n  const unsigned char fullBrightLEDs = 5;  // number of LEDs to leave fully bright\n  const unsigned char cyclePeriod = 14 + fullDarkLEDs + fullBrightLEDs;\n  \n  // if LED_COUNT is not an exact multiple of our repeating pattern size,\n  // it will not wrap around properly, so we pick the closest LED count\n  // that is an exact multiple of the pattern period (cyclePeriod) and is not\n  // smaller than the actual LED count.\n  unsigned int extendedLEDCount = (((LED_COUNT-1)/cyclePeriod)+1)*cyclePeriod;\n\n  j = 0;\n  while (j < extendedLEDCount)\n  {\n    unsigned int idx;\n    \n    // progressively dim the LEDs\n    for (int i = 1; i < 8; i++)\n    {\n      idx = (j + loopCount) % extendedLEDCount;\n      if (j++ >= extendedLEDCount){ return; }\n      if (idx >= LED_COUNT){ continue; }\n  \n      colors[idx].red >>= i;\n      colors[idx].green >>= i;\n      colors[idx].blue >>= i;      \n    }\n    \n    // turn off these LEDs\n    for (int i = 0; i < fullDarkLEDs; i++)\n    {\n      idx = (j + loopCount) % extendedLEDCount;\n      if (j++ >= extendedLEDCount){ return; }\n      if (idx >= LED_COUNT){ continue; }\n  \n      colors[idx].red = 0;\n      colors[idx].green = 0;\n      colors[idx].blue = 0;\n    }\n    \n    // progressively bring these LEDs back\n    for (int i = 0; i < 7; i++)\n    {\n      idx = (j + loopCount) % extendedLEDCount;\n      if (j++ >= extendedLEDCount){ return; }\n      if (idx >= LED_COUNT){ continue; }\n  \n      colors[idx].red >>= (7 - i);\n      colors[idx].green >>= (7 - i);\n      colors[idx].blue >>= (7 - i);      \n    }\n    \n    // skip over these LEDs to leave them at full brightness\n    j += fullBrightLEDs;\n  }\n}\n\n\n// ***** PATTERN BrightTwinkle *****\n// This function creates a sparkling/twinkling effect by randomly\n// picking LEDs to brighten and then fade away.  Possible colors are:\n//   white, red, green, blue, yellow, cyan, and magenta\n// numColors is the number of colors to generate, and minColor\n// indicates the starting point (white is 0, red is 1, ..., and\n// magenta is 6), so colors generated are all of those from minColor\n// to minColor+numColors-1.  For example, calling brightTwinkle(2, 2, 0)\n// will produce green and blue twinkles only.\n// When true, the noNewBursts argument changes prevents the generation\n// of new twinkles; this can be used for a fade-out effect.\n// This function uses a very similar algorithm to the ColorExplosion\n// pattern.  The main difference is that the random twinkling LEDs of\n// this BrightTwinkle pattern do not propagate to neighboring LEDs.\nvoid brightTwinkle(unsigned char minColor, unsigned char numColors, unsigned char noNewBursts)\n{\n  // Note: the colors themselves are used to encode additional state\n  // information.  If the color is one less than a power of two\n  // (but not 255), the color will get approximately twice as bright.\n  // If the color is even, it will fade.  The sequence goes as follows:\n  // * Randomly pick an LED.\n  // * Set the color(s) you want to flash to 1.\n  // * It will automatically grow through 3, 7, 15, 31, 63, 127, 255.\n  // * When it reaches 255, it gets set to 254, which starts the fade\n  //   (the fade process always keeps the color even).\n  for (int i = 0; i < LED_COUNT; i++)\n  {\n    brightTwinkleColorAdjust(&colors[i].red);\n    brightTwinkleColorAdjust(&colors[i].green);\n    brightTwinkleColorAdjust(&colors[i].blue);\n  }\n  \n  if (!noNewBursts)\n  {\n    // if we are generating new twinkles, randomly pick four new LEDs\n    // to light up\n    for (int i = 0; i < 4; i++)\n    {\n      int j = random(LED_COUNT);\n      if (colors[j].red == 0 && colors[j].green == 0 && colors[j].blue == 0)\n      {\n        // if the LED we picked is not already lit, pick a random\n        // color for it and seed it so that it will start getting\n        // brighter in that color\n        switch (random(numColors) + minColor)\n        {\n          case 0:\n            colors[j] = rgb_color(1, 1, 1);  // white\n            break;\n          case 1:\n            colors[j] = rgb_color(1, 0, 0);  // red\n            break;\n          case 2:\n            colors[j] = rgb_color(0, 1, 0);  // green\n            break;\n          case 3:\n            colors[j] = rgb_color(0, 0, 1);  // blue\n            break;\n          case 4:\n            colors[j] = rgb_color(1, 1, 0);  // yellow\n            break;\n          case 5:\n            colors[j] = rgb_color(0, 1, 1);  // cyan\n            break;\n          case 6:\n            colors[j] = rgb_color(1, 0, 1);  // magenta\n            break;\n          default:\n            colors[j] = rgb_color(1, 1, 1);  // white\n        }\n      }\n    }\n  }\n}\n\n\n// ***** PATTERN Collision *****\n// This function spawns streams of color from each end of the strip\n// that collide, at which point the entire strip flashes bright white\n// briefly and then fades.  Unlike the other patterns, this function\n// maintains a lot of complicated state data and tells the main loop\n// when it is done by returning 1 (a return value of 0 means it is\n// still in progress).\nunsigned char collision()\n{\n  const unsigned char maxBrightness = 180;  // max brightness for the colors\n  const unsigned char numCollisions = 5;  // # of collisions before pattern ends\n  static unsigned char state = 0;  // pattern state\n  static unsigned int count = 0;  // counter used by pattern\n  \n  if (loopCount == 0)\n  {\n    state = 0;\n  }\n  \n  if (state % 3 == 0)\n  {\n    // initialization state\n    switch (state/3)\n    {\n      case 0:  // first collision: red streams\n        colors[0] = rgb_color(maxBrightness, 0, 0);\n        break;\n      case 1:  // second collision: green streams\n        colors[0] = rgb_color(0, maxBrightness, 0);\n        break;\n      case 2:  // third collision: blue streams\n        colors[0] = rgb_color(0, 0, maxBrightness);\n        break;\n      case 3:  // fourth collision: warm white streams\n        colors[0] = rgb_color(maxBrightness, maxBrightness*4/5, maxBrightness>>3);\n        break;\n      default:  // fifth collision and beyond: random-color streams\n        colors[0] = rgb_color(random(maxBrightness), random(maxBrightness), random(maxBrightness));\n    }\n    \n    // stream is led by two full-white LEDs\n    colors[1] = colors[2] = rgb_color(255, 255, 255);\n    // make other side of the strip a mirror image of this side\n    colors[LED_COUNT - 1] = colors[0];\n    colors[LED_COUNT - 2] = colors[1];\n    colors[LED_COUNT - 3] = colors[2];\n    \n    state++;  // advance to next state\n    count = 8;  // pick the first value of count that results in a startIdx of 1 (see below)\n    return 0;\n  }\n  \n  if (state % 3 == 1)\n  {\n    // stream-generation state; streams accelerate towards each other\n    unsigned int startIdx = count*(count + 1) >> 6;\n    unsigned int stopIdx = startIdx + (count >> 5);\n    count++;\n    if (startIdx < (LED_COUNT + 1)/2)\n    {\n      // if streams have not crossed the half-way point, keep them growing\n      for (int i = 0; i < startIdx-1; i++)\n      {\n        // start fading previously generated parts of the stream\n        fade(&colors[i].red, 5);\n        fade(&colors[i].green, 5);\n        fade(&colors[i].blue, 5);\n        fade(&colors[LED_COUNT - i - 1].red, 5);\n        fade(&colors[LED_COUNT - i - 1].green, 5);\n        fade(&colors[LED_COUNT - i - 1].blue, 5);\n      }\n      for (int i = startIdx; i <= stopIdx; i++)\n      {\n        // generate new parts of the stream\n        if (i >= (LED_COUNT + 1) / 2)\n        {\n          // anything past the halfway point is white\n          colors[i] = rgb_color(255, 255, 255);\n        }\n        else\n        {\n          colors[i] = colors[i-1];\n        }\n        // make other side of the strip a mirror image of this side\n        colors[LED_COUNT - i - 1] = colors[i];\n      }\n      // stream is led by two full-white LEDs\n      colors[stopIdx + 1] = colors[stopIdx + 2] = rgb_color(255, 255, 255);\n      // make other side of the strip a mirror image of this side\n      colors[LED_COUNT - stopIdx - 2] = colors[stopIdx + 1];\n      colors[LED_COUNT - stopIdx - 3] = colors[stopIdx + 2];\n    }\n    else\n    {\n      // streams have crossed the half-way point of the strip;\n      // flash the entire strip full-brightness white (ignores maxBrightness limits)\n      for (int i = 0; i < LED_COUNT; i++)\n      {\n        colors[i] = rgb_color(255, 255, 255);\n      }\n      state++;  // advance to next state\n    }\n    return 0;\n  }\n  \n  if (state % 3 == 2)\n  {\n    // fade state\n    if (colors[0].red == 0 && colors[0].green == 0 && colors[0].blue == 0)\n    {\n      // if first LED is fully off, advance to next state\n      state++;\n      \n      // after numCollisions collisions, this pattern is done\n      return state == 3*numCollisions;\n    }\n    \n    // fade the LEDs at different rates based on the state\n    for (int i = 0; i < LED_COUNT; i++)\n    {\n      switch (state/3)\n      {\n        case 0:  // fade through green\n          fade(&colors[i].red, 3);\n          fade(&colors[i].green, 4);\n          fade(&colors[i].blue, 2);\n          break;\n        case 1:  // fade through red\n          fade(&colors[i].red, 4);\n          fade(&colors[i].green, 3);\n          fade(&colors[i].blue, 2);\n          break;\n        case 2:  // fade through yellow\n          fade(&colors[i].red, 4);\n          fade(&colors[i].green, 4);\n          fade(&colors[i].blue, 3);\n          break;\n        case 3:  // fade through blue\n          fade(&colors[i].red, 3);\n          fade(&colors[i].green, 2);\n          fade(&colors[i].blue, 4);\n          break;\n        default:  // stay white through entire fade\n          fade(&colors[i].red, 4);\n          fade(&colors[i].green, 4);\n          fade(&colors[i].blue, 4);\n      }\n    }\n  }\n  \n  return 0;\n}\n\n"
  },
  {
    "path": "keywords.txt",
    "content": "Pololu\tKEYWORD1\r\nPololuLedStripBase\tKEYWORD1\r\nPololuLedStrip\tKEYWORD1\r\nrgb_color\tKEYWORD1\r\n\r\nred\tLITERAL1\r\ngreen\tLITERAL1\r\nblue\tLITERAL1\r\n\r\nwrite\tLITERAL1\r\ninterruptFriendly\tLITERAL1"
  },
  {
    "path": "library.properties",
    "content": "name=PololuLedStrip\nversion=4.3.1\nauthor=Pololu\nmaintainer=Pololu <inbox@pololu.com>\nsentence=Arduino library for addressable RGB LED strips from Pololu\nparagraph=This library works with NeoPixels, WS2812B LEDs, and WS2811 LEDs.\ncategory=Device Control\nurl=https://github.com/pololu/pololu-led-strip-arduino\narchitectures=avr,sam\n"
  }
]