libraries / Mitov / MitovEmbedded_Adafruit_NeoPixel / MitovEmbedded_Adafruit_NeoPixel.hon commit Added link to project report (97a3ba0)
   1/*--------------------------------------------------------------------
   2  This file is part of the Adafruit NeoPixel library.
   3
   4  NeoPixel is free software: you can redistribute it and/or modify
   5  it under the terms of the GNU Lesser General Public License as
   6  published by the Free Software Foundation, either version 3 of
   7  the License, or (at your option) any later version.
   8
   9  NeoPixel is distributed in the hope that it will be useful,
  10  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  GNU Lesser General Public License for more details.
  13
  14  You should have received a copy of the GNU Lesser General Public
  15  License along with NeoPixel.  If not, see
  16  <http://www.gnu.org/licenses/>.
  17  --------------------------------------------------------------------*/
  18
  19#ifndef ADAFRUIT_NEOPIXEL_H
  20#define ADAFRUIT_NEOPIXEL_H
  21
  22#if (ARDUINO >= 100)
  23 #include <Arduino.h>
  24#else
  25 #include <WProgram.h>
  26 #include <pins_arduino.h>
  27#endif
  28
  29// 'type' flags for LED pixels (third parameter to constructor):
  30#define NEO_RGB     0x00 // Wired for RGB data order
  31#define NEO_GRB     0x01 // Wired for GRB data order
  32#define NEO_BRG     0x04
  33  
  34#define NEO_COLMASK 0x01
  35#define NEO_KHZ800  0x02 // 800 KHz datastream
  36#define NEO_SPDMASK 0x02
  37// Trinket flash space is tight, v1 NeoPixels aren't handled by default.
  38// Remove the ifndef/endif to add support -- but code will be bigger.
  39// Conversely, can comment out the #defines to save space on other MCUs.
  40#ifndef __AVR_ATtiny85__
  41#define NEO_KHZ400  0x00 // 400 KHz datastream
  42#endif
  43
  44class MitovEmbedded_Adafruit_NeoPixel {
  45
  46 public:
  47
  48  // Constructor: number of LEDs, pin number, LED type
  49  MitovEmbedded_Adafruit_NeoPixel(uint16_t n, uint8_t p=6, uint8_t t=NEO_GRB + NEO_KHZ800);
  50  ~MitovEmbedded_Adafruit_NeoPixel();
  51
  52  void
  53    begin(void),
  54    show(void),
  55    setPin(uint8_t p),
  56    setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
  57    setPixelColor(uint16_t n, uint32_t c),
  58    setBrightness(uint8_t),
  59    clear();
  60  uint8_t
  61   *getPixels(void) const,
  62    getBrightness(void) const;
  63  uint16_t
  64    numPixels(void) const;
  65  static uint32_t
  66    Color(uint8_t r, uint8_t g, uint8_t b);
  67  uint32_t
  68    getPixelColor(uint16_t n) const;
  69  inline bool
  70    canShow(void) { return (micros() - endTime) >= 50L; }
  71
  72 private:
  73
  74  const uint16_t
  75    numLEDs,       // Number of RGB LEDs in strip
  76    numBytes;      // Size of 'pixels' buffer below
  77  uint8_t
  78    pin,           // Output pin number
  79    brightness,
  80   *pixels,        // Holds LED color values (3 bytes each)
  81    rOffset,       // Index of red byte within each 3-byte pixel
  82    gOffset,       // Index of green byte
  83    bOffset;       // Index of blue byte
  84  const uint8_t
  85    type;          // Pixel flags (400 vs 800 KHz, RGB vs GRB color)
  86  uint32_t
  87    endTime;       // Latch timing reference
  88#ifdef __AVR__
  89  const volatile uint8_t
  90    *port;         // Output PORT register
  91  uint8_t
  92    pinMask;       // Output PORT bitmask
  93#endif
  94
  95};
  96
  97MitovEmbedded_Adafruit_NeoPixel::MitovEmbedded_Adafruit_NeoPixel(uint16_t n, uint8_t p, uint8_t t) :
  98   numLEDs(n), numBytes(n * 3), pin(p), brightness(0),
  99   pixels(NULL), type(t), endTime(0)
 100#ifdef __AVR__
 101  ,port(portOutputRegister(digitalPinToPort(p))),
 102   pinMask(digitalPinToBitMask(p))
 103#endif
 104{
 105  if((pixels = (uint8_t *)malloc(numBytes))) {
 106    memset(pixels, 0, numBytes);
 107  }
 108  if(t & NEO_GRB) { // GRB vs RGB; might add others if needed
 109    rOffset = 1;
 110    gOffset = 0;
 111    bOffset = 2;
 112  } else if (t & NEO_BRG) {
 113    rOffset = 1;
 114    gOffset = 2;
 115    bOffset = 0;
 116  } else {
 117    rOffset = 0;
 118    gOffset = 1;
 119    bOffset = 2;
 120  }
 121  
 122}
 123
 124MitovEmbedded_Adafruit_NeoPixel::~MitovEmbedded_Adafruit_NeoPixel() {
 125  if(pixels) free(pixels);
 126  pinMode(pin, INPUT);
 127}
 128
 129void MitovEmbedded_Adafruit_NeoPixel::begin(void) {
 130  pinMode(pin, OUTPUT);
 131  digitalWrite(pin, LOW);
 132}
 133
 134void MitovEmbedded_Adafruit_NeoPixel::show(void) {
 135
 136  if(!pixels) return;
 137
 138  // Data latch = 50+ microsecond pause in the output stream.  Rather than
 139  // put a delay at the end of the function, the ending time is noted and
 140  // the function will simply hold off (if needed) on issuing the
 141  // subsequent round of data until the latch time has elapsed.  This
 142  // allows the mainline code to start generating the next frame of data
 143  // rather than stalling for the latch.
 144  while(!canShow());
 145  // endTime is a private member (rather than global var) so that mutliple
 146  // instances on different pins can be quickly issued in succession (each
 147  // instance doesn't delay the next).
 148
 149  // In order to make this code runtime-configurable to work with any pin,
 150  // SBI/CBI instructions are eschewed in favor of full PORT writes via the
 151  // OUT or ST instructions.  It relies on two facts: that peripheral
 152  // functions (such as PWM) take precedence on output pins, so our PORT-
 153  // wide writes won't interfere, and that interrupts are globally disabled
 154  // while data is being issued to the LEDs, so no other code will be
 155  // accessing the PORT.  The code takes an initial 'snapshot' of the PORT
 156  // state, computes 'pin high' and 'pin low' values, and writes these back
 157  // to the PORT register as needed.
 158
 159  noInterrupts(); // Need 100% focus on instruction timing
 160
 161#ifdef __AVR__
 162
 163  volatile uint16_t
 164    i   = numBytes; // Loop counter
 165  volatile uint8_t
 166   *ptr = pixels,   // Pointer to next byte
 167    b   = *ptr++,   // Current byte value
 168    hi,             // PORT w/output bit set high
 169    lo;             // PORT w/output bit set low
 170
 171  // Hand-tuned assembly code issues data to the LED drivers at a specific
 172  // rate.  There's separate code for different CPU speeds (8, 12, 16 MHz)
 173  // for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers.  The
 174  // datastream timing for the LED drivers allows a little wiggle room each
 175  // way (listed in the datasheets), so the conditions for compiling each
 176  // case are set up for a range of frequencies rather than just the exact
 177  // 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on
 178  // devices (e.g. 16.5 MHz DigiSpark).  The ranges were arrived at based
 179  // on the datasheet figures and have not been extensively tested outside
 180  // the canonical 8/12/16 MHz speeds; there's no guarantee these will work
 181  // close to the extremes (or possibly they could be pushed further).
 182  // Keep in mind only one CPU speed case actually gets compiled; the
 183  // resulting program isn't as massive as it might look from source here.
 184
 185// 8 MHz(ish) AVR ---------------------------------------------------------
 186#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
 187
 188#ifdef NEO_KHZ400
 189  if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
 190#endif
 191
 192    volatile uint8_t n1, n2 = 0;  // First, next bits out
 193
 194    // Squeezing an 800 KHz stream out of an 8 MHz chip requires code
 195    // specific to each PORT register.  At present this is only written
 196    // to work with pins on PORTD or PORTB, the most likely use case --
 197    // this covers all the pins on the Adafruit Flora and the bulk of
 198    // digital pins on the Arduino Pro 8 MHz (keep in mind, this code
 199    // doesn't even get compiled for 16 MHz boards like the Uno, Mega,
 200    // Leonardo, etc., so don't bother extending this out of hand).
 201    // Additional PORTs could be added if you really need them, just
 202    // duplicate the else and loop and change the PORT.  Each add'l
 203    // PORT will require about 150(ish) bytes of program space.
 204
 205    // 10 instruction clocks per bit: HHxxxxxLLL
 206    // OUT instructions:              ^ ^    ^   (T=0,2,7)
 207
 208#ifdef PORTD // PORTD isn't present on ATtiny85, etc.
 209
 210    if(port == &PORTD) {
 211
 212      hi = PORTD |  pinMask;
 213      lo = PORTD & ~pinMask;
 214      n1 = lo;
 215      if(b & 0x80) n1 = hi;
 216
 217      // Dirty trick: RJMPs proceeding to the next instruction are used
 218      // to delay two clock cycles in one instruction word (rather than
 219      // using two NOPs).  This was necessary in order to squeeze the
 220      // loop down to exactly 64 words -- the maximum possible for a
 221      // relative branch.
 222
 223      asm volatile(
 224       "headD:"                   "\n\t" // Clk  Pseudocode
 225        // Bit 7:
 226        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 227        "mov  %[n2]   , %[lo]"    "\n\t" // 1    n2   = lo
 228        "out  %[port] , %[n1]"    "\n\t" // 1    PORT = n1
 229        "rjmp .+0"                "\n\t" // 2    nop nop
 230        "sbrc %[byte] , 6"        "\n\t" // 1-2  if(b & 0x40)
 231         "mov %[n2]   , %[hi]"    "\n\t" // 0-1   n2 = hi
 232        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 233        "rjmp .+0"                "\n\t" // 2    nop nop
 234        // Bit 6:
 235        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 236        "mov  %[n1]   , %[lo]"    "\n\t" // 1    n1   = lo
 237        "out  %[port] , %[n2]"    "\n\t" // 1    PORT = n2
 238        "rjmp .+0"                "\n\t" // 2    nop nop
 239        "sbrc %[byte] , 5"        "\n\t" // 1-2  if(b & 0x20)
 240         "mov %[n1]   , %[hi]"    "\n\t" // 0-1   n1 = hi
 241        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 242        "rjmp .+0"                "\n\t" // 2    nop nop
 243        // Bit 5:
 244        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 245        "mov  %[n2]   , %[lo]"    "\n\t" // 1    n2   = lo
 246        "out  %[port] , %[n1]"    "\n\t" // 1    PORT = n1
 247        "rjmp .+0"                "\n\t" // 2    nop nop
 248        "sbrc %[byte] , 4"        "\n\t" // 1-2  if(b & 0x10)
 249         "mov %[n2]   , %[hi]"    "\n\t" // 0-1   n2 = hi
 250        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 251        "rjmp .+0"                "\n\t" // 2    nop nop
 252        // Bit 4:
 253        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 254        "mov  %[n1]   , %[lo]"    "\n\t" // 1    n1   = lo
 255        "out  %[port] , %[n2]"    "\n\t" // 1    PORT = n2
 256        "rjmp .+0"                "\n\t" // 2    nop nop
 257        "sbrc %[byte] , 3"        "\n\t" // 1-2  if(b & 0x08)
 258         "mov %[n1]   , %[hi]"    "\n\t" // 0-1   n1 = hi
 259        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 260        "rjmp .+0"                "\n\t" // 2    nop nop
 261        // Bit 3:
 262        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 263        "mov  %[n2]   , %[lo]"    "\n\t" // 1    n2   = lo
 264        "out  %[port] , %[n1]"    "\n\t" // 1    PORT = n1
 265        "rjmp .+0"                "\n\t" // 2    nop nop
 266        "sbrc %[byte] , 2"        "\n\t" // 1-2  if(b & 0x04)
 267         "mov %[n2]   , %[hi]"    "\n\t" // 0-1   n2 = hi
 268        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 269        "rjmp .+0"                "\n\t" // 2    nop nop
 270        // Bit 2:
 271        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 272        "mov  %[n1]   , %[lo]"    "\n\t" // 1    n1   = lo
 273        "out  %[port] , %[n2]"    "\n\t" // 1    PORT = n2
 274        "rjmp .+0"                "\n\t" // 2    nop nop
 275        "sbrc %[byte] , 1"        "\n\t" // 1-2  if(b & 0x02)
 276         "mov %[n1]   , %[hi]"    "\n\t" // 0-1   n1 = hi
 277        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 278        "rjmp .+0"                "\n\t" // 2    nop nop
 279        // Bit 1:
 280        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 281        "mov  %[n2]   , %[lo]"    "\n\t" // 1    n2   = lo
 282        "out  %[port] , %[n1]"    "\n\t" // 1    PORT = n1
 283        "rjmp .+0"                "\n\t" // 2    nop nop
 284        "sbrc %[byte] , 0"        "\n\t" // 1-2  if(b & 0x01)
 285         "mov %[n2]   , %[hi]"    "\n\t" // 0-1   n2 = hi
 286        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 287        "sbiw %[count], 1"        "\n\t" // 2    i-- (don't act on Z flag yet)
 288        // Bit 0:
 289        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
 290        "mov  %[n1]   , %[lo]"    "\n\t" // 1    n1   = lo
 291        "out  %[port] , %[n2]"    "\n\t" // 1    PORT = n2
 292        "ld   %[byte] , %a[ptr]+" "\n\t" // 2    b = *ptr++
 293        "sbrc %[byte] , 7"        "\n\t" // 1-2  if(b & 0x80)
 294         "mov %[n1]   , %[hi]"    "\n\t" // 0-1   n1 = hi
 295        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
 296        "brne headD"              "\n"   // 2    while(i) (Z flag set above)
 297      : [byte]  "+r" (b),
 298        [n1]    "+r" (n1),
 299        [n2]    "+r" (n2),
 300        [count] "+w" (i)
 301      : [port]   "I" (_SFR_IO_ADDR(PORTD)),
 302        [ptr]    "e" (ptr),
 303        [hi]     "r" (hi),
 304        [lo]     "r" (lo));
 305
 306    } else if(port == &PORTB) {
 307
 308#endif // PORTD
 309
 310      // Same as above, just switched to PORTB and stripped of comments.
 311      hi = PORTB |  pinMask;
 312      lo = PORTB & ~pinMask;
 313      n1 = lo;
 314      if(b & 0x80) n1 = hi;
 315
 316      asm volatile(
 317       "headB:"                   "\n\t"
 318        "out  %[port] , %[hi]"    "\n\t"
 319        "mov  %[n2]   , %[lo]"    "\n\t"
 320        "out  %[port] , %[n1]"    "\n\t"
 321        "rjmp .+0"                "\n\t"
 322        "sbrc %[byte] , 6"        "\n\t"
 323         "mov %[n2]   , %[hi]"    "\n\t"
 324        "out  %[port] , %[lo]"    "\n\t"
 325        "rjmp .+0"                "\n\t"
 326        "out  %[port] , %[hi]"    "\n\t"
 327        "mov  %[n1]   , %[lo]"    "\n\t"
 328        "out  %[port] , %[n2]"    "\n\t"
 329        "rjmp .+0"                "\n\t"
 330        "sbrc %[byte] , 5"        "\n\t"
 331         "mov %[n1]   , %[hi]"    "\n\t"
 332        "out  %[port] , %[lo]"    "\n\t"
 333        "rjmp .+0"                "\n\t"
 334        "out  %[port] , %[hi]"    "\n\t"
 335        "mov  %[n2]   , %[lo]"    "\n\t"
 336        "out  %[port] , %[n1]"    "\n\t"
 337        "rjmp .+0"                "\n\t"
 338        "sbrc %[byte] , 4"        "\n\t"
 339         "mov %[n2]   , %[hi]"    "\n\t"
 340        "out  %[port] , %[lo]"    "\n\t"
 341        "rjmp .+0"                "\n\t"
 342        "out  %[port] , %[hi]"    "\n\t"
 343        "mov  %[n1]   , %[lo]"    "\n\t"
 344        "out  %[port] , %[n2]"    "\n\t"
 345        "rjmp .+0"                "\n\t"
 346        "sbrc %[byte] , 3"        "\n\t"
 347         "mov %[n1]   , %[hi]"    "\n\t"
 348        "out  %[port] , %[lo]"    "\n\t"
 349        "rjmp .+0"                "\n\t"
 350        "out  %[port] , %[hi]"    "\n\t"
 351        "mov  %[n2]   , %[lo]"    "\n\t"
 352        "out  %[port] , %[n1]"    "\n\t"
 353        "rjmp .+0"                "\n\t"
 354        "sbrc %[byte] , 2"        "\n\t"
 355         "mov %[n2]   , %[hi]"    "\n\t"
 356        "out  %[port] , %[lo]"    "\n\t"
 357        "rjmp .+0"                "\n\t"
 358        "out  %[port] , %[hi]"    "\n\t"
 359        "mov  %[n1]   , %[lo]"    "\n\t"
 360        "out  %[port] , %[n2]"    "\n\t"
 361        "rjmp .+0"                "\n\t"
 362        "sbrc %[byte] , 1"        "\n\t"
 363         "mov %[n1]   , %[hi]"    "\n\t"
 364        "out  %[port] , %[lo]"    "\n\t"
 365        "rjmp .+0"                "\n\t"
 366        "out  %[port] , %[hi]"    "\n\t"
 367        "mov  %[n2]   , %[lo]"    "\n\t"
 368        "out  %[port] , %[n1]"    "\n\t"
 369        "rjmp .+0"                "\n\t"
 370        "sbrc %[byte] , 0"        "\n\t"
 371         "mov %[n2]   , %[hi]"    "\n\t"
 372        "out  %[port] , %[lo]"    "\n\t"
 373        "sbiw %[count], 1"        "\n\t"
 374        "out  %[port] , %[hi]"    "\n\t"
 375        "mov  %[n1]   , %[lo]"    "\n\t"
 376        "out  %[port] , %[n2]"    "\n\t"
 377        "ld   %[byte] , %a[ptr]+" "\n\t"
 378        "sbrc %[byte] , 7"        "\n\t"
 379         "mov %[n1]   , %[hi]"    "\n\t"
 380        "out  %[port] , %[lo]"    "\n\t"
 381        "brne headB"              "\n"
 382      : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
 383      : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
 384        [lo] "r" (lo));
 385
 386#ifdef PORTD
 387    }    // endif PORTB
 388#endif
 389
 390#ifdef NEO_KHZ400
 391  } else { // end 800 KHz, do 400 KHz
 392
 393    // Timing is more relaxed; unrolling the inner loop for each bit is
 394    // not necessary.  Still using the peculiar RJMPs as 2X NOPs, not out
 395    // of need but just to trim the code size down a little.
 396    // This 400-KHz-datastream-on-8-MHz-CPU code is not quite identical
 397    // to the 800-on-16 code later -- the hi/lo timing between WS2811 and
 398    // WS2812 is not simply a 2:1 scale!
 399
 400    // 20 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL
 401    // ST instructions:         ^   ^     ^          (T=0,4,10)
 402
 403    volatile uint8_t next, bit;
 404
 405    hi   = *port |  pinMask;
 406    lo   = *port & ~pinMask;
 407    next = lo;
 408    bit  = 8;
 409
 410    asm volatile(
 411     "head20:"                  "\n\t" // Clk  Pseudocode    (T =  0)
 412      "st   %a[port], %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
 413      "sbrc %[byte] , 7"        "\n\t" // 1-2  if(b & 128)
 414       "mov  %[next], %[hi]"    "\n\t" // 0-1   next = hi    (T =  4)
 415      "st   %a[port], %[next]"  "\n\t" // 2    PORT = next   (T =  6)
 416      "mov  %[next] , %[lo]"    "\n\t" // 1    next = lo     (T =  7)
 417      "dec  %[bit]"             "\n\t" // 1    bit--         (T =  8)
 418      "breq nextbyte20"         "\n\t" // 1-2  if(bit == 0)
 419      "rol  %[byte]"            "\n\t" // 1    b <<= 1       (T = 10)
 420      "st   %a[port], %[lo]"    "\n\t" // 2    PORT = lo     (T = 12)
 421      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 14)
 422      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 16)
 423      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 18)
 424      "rjmp head20"             "\n\t" // 2    -> head20 (next bit out)
 425     "nextbyte20:"              "\n\t" //                    (T = 10)
 426      "st   %a[port], %[lo]"    "\n\t" // 2    PORT = lo     (T = 12)
 427      "nop"                     "\n\t" // 1    nop           (T = 13)
 428      "ldi  %[bit]  , 8"        "\n\t" // 1    bit = 8       (T = 14)
 429      "ld   %[byte] , %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 16)
 430      "sbiw %[count], 1"        "\n\t" // 2    i--           (T = 18)
 431      "brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
 432      : [port]  "+e" (port),
 433        [byte]  "+r" (b),
 434        [bit]   "+r" (bit),
 435        [next]  "+r" (next),
 436        [count] "+w" (i)
 437      : [hi]    "r" (hi),
 438        [lo]    "r" (lo),
 439        [ptr]   "e" (ptr));
 440  }
 441#endif
 442
 443// 12 MHz(ish) AVR --------------------------------------------------------
 444#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
 445
 446#ifdef NEO_KHZ400
 447  if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
 448#endif
 449
 450    // In the 12 MHz case, an optimized 800 KHz datastream (no dead time
 451    // between bytes) requires a PORT-specific loop similar to the 8 MHz
 452    // code (but a little more relaxed in this case).
 453
 454    // 15 instruction clocks per bit: HHHHxxxxxxLLLLL
 455    // OUT instructions:              ^   ^     ^     (T=0,4,10)
 456
 457    volatile uint8_t next;
 458
 459#ifdef PORTD
 460
 461    if(port == &PORTD) {
 462
 463      hi   = PORTD |  pinMask;
 464      lo   = PORTD & ~pinMask;
 465      next = lo;
 466      if(b & 0x80) next = hi;
 467
 468      // Don't "optimize" the OUT calls into the bitTime subroutine;
 469      // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
 470      asm volatile(
 471       "headD:"                   "\n\t" //        (T =  0)
 472        "out   %[port], %[hi]"    "\n\t" //        (T =  1)
 473        "rcall bitTimeD"          "\n\t" // Bit 7  (T = 15)
 474        "out   %[port], %[hi]"    "\n\t"
 475        "rcall bitTimeD"          "\n\t" // Bit 6
 476        "out   %[port], %[hi]"    "\n\t"
 477        "rcall bitTimeD"          "\n\t" // Bit 5
 478        "out   %[port], %[hi]"    "\n\t"
 479        "rcall bitTimeD"          "\n\t" // Bit 4
 480        "out   %[port], %[hi]"    "\n\t"
 481        "rcall bitTimeD"          "\n\t" // Bit 3
 482        "out   %[port], %[hi]"    "\n\t"
 483        "rcall bitTimeD"          "\n\t" // Bit 2
 484        "out   %[port], %[hi]"    "\n\t"
 485        "rcall bitTimeD"          "\n\t" // Bit 1
 486        // Bit 0:
 487        "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi    (T =  1)
 488        "rjmp .+0"                "\n\t" // 2    nop nop      (T =  3)
 489        "ld   %[byte] , %a[ptr]+" "\n\t" // 2    b = *ptr++   (T =  5)
 490        "out  %[port] , %[next]"  "\n\t" // 1    PORT = next  (T =  6)
 491        "mov  %[next] , %[lo]"    "\n\t" // 1    next = lo    (T =  7)
 492        "sbrc %[byte] , 7"        "\n\t" // 1-2  if(b & 0x80) (T =  8)
 493         "mov %[next] , %[hi]"    "\n\t" // 0-1    next = hi  (T =  9)
 494        "nop"                     "\n\t" // 1                 (T = 10)
 495        "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo    (T = 11)
 496        "sbiw %[count], 1"        "\n\t" // 2    i--          (T = 13)
 497        "brne headD"              "\n\t" // 2    if(i != 0) -> (next byte)
 498         "rjmp doneD"             "\n\t"
 499        "bitTimeD:"               "\n\t" //      nop nop nop     (T =  4)
 500         "out  %[port], %[next]"  "\n\t" // 1    PORT = next     (T =  5)
 501         "mov  %[next], %[lo]"    "\n\t" // 1    next = lo       (T =  6)
 502         "rol  %[byte]"           "\n\t" // 1    b <<= 1         (T =  7)
 503         "sbrc %[byte], 7"        "\n\t" // 1-2  if(b & 0x80)    (T =  8)
 504          "mov %[next], %[hi]"    "\n\t" // 0-1   next = hi      (T =  9)
 505         "nop"                    "\n\t" // 1                    (T = 10)
 506         "out  %[port], %[lo]"    "\n\t" // 1    PORT = lo       (T = 11)
 507         "ret"                    "\n\t" // 4    nop nop nop nop (T = 15)
 508         "doneD:"                 "\n"
 509        : [byte]  "+r" (b),
 510          [next]  "+r" (next),
 511          [count] "+w" (i)
 512        : [port]   "I" (_SFR_IO_ADDR(PORTD)),
 513          [ptr]    "e" (ptr),
 514          [hi]     "r" (hi),
 515          [lo]     "r" (lo));
 516
 517    } else if(port == &PORTB) {
 518
 519#endif // PORTD
 520
 521      hi   = PORTB |  pinMask;
 522      lo   = PORTB & ~pinMask;
 523      next = lo;
 524      if(b & 0x80) next = hi;
 525
 526      // Same as above, just set for PORTB & stripped of comments
 527      asm volatile(
 528       "headB:"                   "\n\t"
 529        "out   %[port], %[hi]"    "\n\t"
 530        "rcall bitTimeB"          "\n\t"
 531        "out   %[port], %[hi]"    "\n\t"
 532        "rcall bitTimeB"          "\n\t"
 533        "out   %[port], %[hi]"    "\n\t"
 534        "rcall bitTimeB"          "\n\t"
 535        "out   %[port], %[hi]"    "\n\t"
 536        "rcall bitTimeB"          "\n\t"
 537        "out   %[port], %[hi]"    "\n\t"
 538        "rcall bitTimeB"          "\n\t"
 539        "out   %[port], %[hi]"    "\n\t"
 540        "rcall bitTimeB"          "\n\t"
 541        "out   %[port], %[hi]"    "\n\t"
 542        "rcall bitTimeB"          "\n\t"
 543        "out  %[port] , %[hi]"    "\n\t"
 544        "rjmp .+0"                "\n\t"
 545        "ld   %[byte] , %a[ptr]+" "\n\t"
 546        "out  %[port] , %[next]"  "\n\t"
 547        "mov  %[next] , %[lo]"    "\n\t"
 548        "sbrc %[byte] , 7"        "\n\t"
 549         "mov %[next] , %[hi]"    "\n\t"
 550        "nop"                     "\n\t"
 551        "out  %[port] , %[lo]"    "\n\t"
 552        "sbiw %[count], 1"        "\n\t"
 553        "brne headB"              "\n\t"
 554         "rjmp doneB"             "\n\t"
 555        "bitTimeB:"               "\n\t"
 556         "out  %[port], %[next]"  "\n\t"
 557         "mov  %[next], %[lo]"    "\n\t"
 558         "rol  %[byte]"           "\n\t"
 559         "sbrc %[byte], 7"        "\n\t"
 560          "mov %[next], %[hi]"    "\n\t"
 561         "nop"                    "\n\t"
 562         "out  %[port], %[lo]"    "\n\t"
 563         "ret"                    "\n\t"
 564         "doneB:"                 "\n"
 565        : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
 566        : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
 567          [lo] "r" (lo));
 568
 569#ifdef PORTD
 570    }
 571#endif
 572
 573#ifdef NEO_KHZ400
 574  } else { // 400 KHz
 575
 576    // 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL
 577    // ST instructions:               ^     ^        ^    (T=0,6,15)
 578
 579    volatile uint8_t next, bit;
 580
 581    hi   = *port |  pinMask;
 582    lo   = *port & ~pinMask;
 583    next = lo;
 584    bit  = 8;
 585
 586    asm volatile(
 587     "head30:"                  "\n\t" // Clk  Pseudocode    (T =  0)
 588      "st   %a[port], %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
 589      "sbrc %[byte] , 7"        "\n\t" // 1-2  if(b & 128)
 590       "mov  %[next], %[hi]"    "\n\t" // 0-1   next = hi    (T =  4)
 591      "rjmp .+0"                "\n\t" // 2    nop nop       (T =  6)
 592      "st   %a[port], %[next]"  "\n\t" // 2    PORT = next   (T =  8)
 593      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 10)
 594      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 12)
 595      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 14)
 596      "nop"                     "\n\t" // 1    nop           (T = 15)
 597      "st   %a[port], %[lo]"    "\n\t" // 2    PORT = lo     (T = 17)
 598      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 19)
 599      "dec  %[bit]"             "\n\t" // 1    bit--         (T = 20)
 600      "breq nextbyte30"         "\n\t" // 1-2  if(bit == 0)
 601      "rol  %[byte]"            "\n\t" // 1    b <<= 1       (T = 22)
 602      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 24)
 603      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 26)
 604      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 28)
 605      "rjmp head30"             "\n\t" // 2    -> head30 (next bit out)
 606     "nextbyte30:"              "\n\t" //                    (T = 22)
 607      "nop"                     "\n\t" // 1    nop           (T = 23)
 608      "ldi  %[bit]  , 8"        "\n\t" // 1    bit = 8       (T = 24)
 609      "ld   %[byte] , %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 26)
 610      "sbiw %[count], 1"        "\n\t" // 2    i--           (T = 28)
 611      "brne head30"             "\n"   // 1-2  if(i != 0) -> (next byte)
 612      : [port]  "+e" (port),
 613        [byte]  "+r" (b),
 614        [bit]   "+r" (bit),
 615        [next]  "+r" (next),
 616        [count] "+w" (i)
 617      : [hi]     "r" (hi),
 618        [lo]     "r" (lo),
 619        [ptr]    "e" (ptr));
 620  }
 621#endif
 622
 623// 16 MHz(ish) AVR --------------------------------------------------------
 624#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
 625
 626#ifdef NEO_KHZ400
 627  if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
 628#endif
 629
 630    // WS2811 and WS2812 have different hi/lo duty cycles; this is
 631    // similar but NOT an exact copy of the prior 400-on-8 code.
 632
 633    // 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL
 634    // ST instructions:         ^   ^        ^       (T=0,5,13)
 635
 636    volatile uint8_t next, bit;
 637
 638    hi   = *port |  pinMask;
 639    lo   = *port & ~pinMask;
 640    next = lo;
 641    bit  = 8;
 642
 643    asm volatile(
 644     "head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
 645      "st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
 646      "sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
 647       "mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
 648      "dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
 649      "st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
 650      "mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
 651      "breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
 652      "rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
 653      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
 654      "nop"                      "\n\t" // 1    nop           (T = 13)
 655      "st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
 656      "nop"                      "\n\t" // 1    nop           (T = 16)
 657      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
 658      "rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
 659     "nextbyte20:"               "\n\t" //                    (T = 10)
 660      "ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
 661      "ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
 662      "st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
 663      "nop"                      "\n\t" // 1    nop           (T = 16)
 664      "sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
 665       "brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
 666      : [port]  "+e" (port),
 667        [byte]  "+r" (b),
 668        [bit]   "+r" (bit),
 669        [next]  "+r" (next),
 670        [count] "+w" (i)
 671      : [ptr]    "e" (ptr),
 672        [hi]     "r" (hi),
 673        [lo]     "r" (lo));
 674
 675#ifdef NEO_KHZ400
 676  } else { // 400 KHz
 677
 678    // The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version.
 679
 680    // 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL
 681    // ST instructions:         ^       ^           ^         (T=0,8,20)
 682
 683    volatile uint8_t next, bit;
 684
 685    hi   = *port |  pinMask;
 686    lo   = *port & ~pinMask;
 687    next = lo;
 688    bit  = 8;
 689
 690    asm volatile(
 691     "head40:"                  "\n\t" // Clk  Pseudocode    (T =  0)
 692      "st   %a[port], %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
 693      "sbrc %[byte] , 7"        "\n\t" // 1-2  if(b & 128)
 694       "mov  %[next] , %[hi]"   "\n\t" // 0-1   next = hi    (T =  4)
 695      "rjmp .+0"                "\n\t" // 2    nop nop       (T =  6)
 696      "rjmp .+0"                "\n\t" // 2    nop nop       (T =  8)
 697      "st   %a[port], %[next]"  "\n\t" // 2    PORT = next   (T = 10)
 698      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 12)
 699      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 14)
 700      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 16)
 701      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 18)
 702      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 20)
 703      "st   %a[port], %[lo]"    "\n\t" // 2    PORT = lo     (T = 22)
 704      "nop"                     "\n\t" // 1    nop           (T = 23)
 705      "mov  %[next] , %[lo]"    "\n\t" // 1    next = lo     (T = 24)
 706      "dec  %[bit]"             "\n\t" // 1    bit--         (T = 25)
 707      "breq nextbyte40"         "\n\t" // 1-2  if(bit == 0)
 708      "rol  %[byte]"            "\n\t" // 1    b <<= 1       (T = 27)
 709      "nop"                     "\n\t" // 1    nop           (T = 28)
 710      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 30)
 711      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 32)
 712      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 34)
 713      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 36)
 714      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 38)
 715      "rjmp head40"             "\n\t" // 2    -> head40 (next bit out)
 716     "nextbyte40:"              "\n\t" //                    (T = 27)
 717      "ldi  %[bit]  , 8"        "\n\t" // 1    bit = 8       (T = 28)
 718      "ld   %[byte] , %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 30)
 719      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 32)
 720      "st   %a[port], %[lo]"    "\n\t" // 2    PORT = lo     (T = 34)
 721      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 36)
 722      "sbiw %[count], 1"        "\n\t" // 2    i--           (T = 38)
 723      "brne head40"             "\n"   // 1-2  if(i != 0) -> (next byte)
 724      : [port]  "+e" (port),
 725        [byte]  "+r" (b),
 726        [bit]   "+r" (bit),
 727        [next]  "+r" (next),
 728        [count] "+w" (i)
 729      : [ptr]    "e" (ptr),
 730        [hi]     "r" (hi),
 731        [lo]     "r" (lo));
 732  }
 733#endif
 734
 735#else
 736 #error "CPU SPEED NOT SUPPORTED"
 737#endif
 738
 739#elif defined(__arm__)
 740
 741#if defined(__MK20DX128__) || defined(__MK20DX256__) // Teensy 3.0 & 3.1
 742#define CYCLES_800_T0H  (F_CPU / 4000000)
 743#define CYCLES_800_T1H  (F_CPU / 1250000)
 744#define CYCLES_800      (F_CPU /  800000)
 745#define CYCLES_400_T0H  (F_CPU / 2000000)
 746#define CYCLES_400_T1H  (F_CPU /  833333)
 747#define CYCLES_400      (F_CPU /  400000)
 748
 749  uint8_t          *p   = pixels,
 750                   *end = p + numBytes, pix, mask;
 751  volatile uint8_t *set = portSetRegister(pin),
 752                   *clr = portClearRegister(pin);
 753  uint32_t          cyc;
 754
 755  ARM_DEMCR    |= ARM_DEMCR_TRCENA;
 756  ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
 757
 758#ifdef NEO_KHZ400
 759  if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
 760#endif
 761    cyc = ARM_DWT_CYCCNT + CYCLES_800;
 762    while(p < end) {
 763      pix = *p++;
 764      for(mask = 0x80; mask; mask >>= 1) {
 765        while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
 766        cyc  = ARM_DWT_CYCCNT;
 767        *set = 1;
 768        if(pix & mask) {
 769          while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H);
 770        } else {
 771          while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H);
 772        }
 773        *clr = 1;
 774      }
 775    }
 776    while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
 777#ifdef NEO_KHZ400
 778  } else { // 400 kHz bitstream
 779    cyc = ARM_DWT_CYCCNT + CYCLES_400;
 780    while(p < end) {
 781      pix = *p++;
 782      for(mask = 0x80; mask; mask >>= 1) {
 783        while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
 784        cyc  = ARM_DWT_CYCCNT;
 785        *set = 1;
 786        if(pix & mask) {
 787          while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H);
 788        } else {
 789          while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H);
 790        }
 791        *clr = 1;
 792      }
 793    }
 794    while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
 795  }
 796#endif
 797
 798
 799
 800
 801
 802#elif defined(__MKL26Z64__) // Teensy-LC
 803
 804#if F_CPU == 48000000
 805  uint8_t          *p   = pixels,
 806                   pix, count, dly,
 807                   bitmask = digitalPinToBitMask(pin);
 808  volatile uint8_t *reg = portSetRegister(pin);
 809  uint32_t         num = numBytes;
 810  asm volatile(
 811        "L%=_begin:"                            "\n\t"
 812        "ldrb   %[pix], [%[p], #0]"             "\n\t"
 813        "lsl    %[pix], #24"                    "\n\t"
 814        "movs   %[count], #7"                   "\n\t"
 815        "L%=_loop:"                             "\n\t"
 816        "lsl    %[pix], #1"                     "\n\t"
 817        "bcs    L%=_loop_one"                   "\n\t"
 818        "L%=_loop_zero:"
 819        "strb   %[bitmask], [%[reg], #0]"       "\n\t"
 820        "movs   %[dly], #4"                     "\n\t"
 821        "L%=_loop_delay_T0H:"                   "\n\t"
 822        "sub    %[dly], #1"                     "\n\t"
 823        "bne    L%=_loop_delay_T0H"             "\n\t"
 824        "strb   %[bitmask], [%[reg], #4]"       "\n\t"
 825        "movs   %[dly], #13"                    "\n\t"
 826        "L%=_loop_delay_T0L:"                   "\n\t"
 827        "sub    %[dly], #1"                     "\n\t"
 828        "bne    L%=_loop_delay_T0L"             "\n\t"
 829        "b      L%=_next"                       "\n\t"
 830        "L%=_loop_one:"
 831        "strb   %[bitmask], [%[reg], #0]"       "\n\t"
 832        "movs   %[dly], #13"                    "\n\t"
 833        "L%=_loop_delay_T1H:"                   "\n\t"
 834        "sub    %[dly], #1"                     "\n\t"
 835        "bne    L%=_loop_delay_T1H"             "\n\t"
 836        "strb   %[bitmask], [%[reg], #4]"       "\n\t"
 837        "movs   %[dly], #4"                     "\n\t"
 838        "L%=_loop_delay_T1L:"                   "\n\t"
 839        "sub    %[dly], #1"                     "\n\t"
 840        "bne    L%=_loop_delay_T1L"             "\n\t"
 841        "nop"                                   "\n\t"
 842        "L%=_next:"                             "\n\t"
 843        "sub    %[count], #1"                   "\n\t"
 844        "bne    L%=_loop"                       "\n\t"
 845        "lsl    %[pix], #1"                     "\n\t"
 846        "bcs    L%=_last_one"                   "\n\t"
 847        "L%=_last_zero:"
 848        "strb   %[bitmask], [%[reg], #0]"       "\n\t"
 849        "movs   %[dly], #4"                     "\n\t"
 850        "L%=_last_delay_T0H:"                   "\n\t"
 851        "sub    %[dly], #1"                     "\n\t"
 852        "bne    L%=_last_delay_T0H"             "\n\t"
 853        "strb   %[bitmask], [%[reg], #4]"       "\n\t"
 854        "movs   %[dly], #10"                    "\n\t"
 855        "L%=_last_delay_T0L:"                   "\n\t"
 856        "sub    %[dly], #1"                     "\n\t"
 857        "bne    L%=_last_delay_T0L"             "\n\t"
 858        "b      L%=_repeat"                     "\n\t"
 859        "L%=_last_one:"
 860        "strb   %[bitmask], [%[reg], #0]"       "\n\t"
 861        "movs   %[dly], #13"                    "\n\t"
 862        "L%=_last_delay_T1H:"                   "\n\t"
 863        "sub    %[dly], #1"                     "\n\t"
 864        "bne    L%=_last_delay_T1H"             "\n\t"
 865        "strb   %[bitmask], [%[reg], #4]"       "\n\t"
 866        "movs   %[dly], #1"                     "\n\t"
 867        "L%=_last_delay_T1L:"                   "\n\t"
 868        "sub    %[dly], #1"                     "\n\t"
 869        "bne    L%=_last_delay_T1L"             "\n\t"
 870        "nop"                                   "\n\t"
 871        "L%=_repeat:"                           "\n\t"
 872        "add    %[p], #1"                       "\n\t"
 873        "sub    %[num], #1"                     "\n\t"
 874        "bne    L%=_begin"                      "\n\t"
 875        "L%=_done:"                             "\n\t"
 876        : [p] "+r" (p),
 877          [pix] "=&r" (pix),
 878          [count] "=&r" (count),
 879          [dly] "=&r" (dly),
 880          [num] "+r" (num)
 881        : [bitmask] "r" (bitmask),
 882          [reg] "r" (reg)
 883  );
 884#else
 885#error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
 886#endif
 887
 888
 889#else // Arduino Due
 890
 891  #define SCALE      VARIANT_MCK / 2UL / 1000000UL
 892  #define INST       (2UL * F_CPU / VARIANT_MCK)
 893  #define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST))
 894  #define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST))
 895  #define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST))
 896  #define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST))
 897  #define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST))
 898  #define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST))
 899
 900  int             pinMask, time0, time1, period, t;
 901  Pio            *port;
 902  volatile WoReg *portSet, *portClear, *timeValue, *timeReset;
 903  uint8_t        *p, *end, pix, mask;
 904
 905  pmc_set_writeprotect(false);
 906  pmc_enable_periph_clk((uint32_t)TC3_IRQn);
 907  TC_Configure(TC1, 0,
 908    TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1);
 909  TC_Start(TC1, 0);
 910
 911  pinMask   = g_APinDescription[pin].ulPin; // Don't 'optimize' these into
 912  port      = g_APinDescription[pin].pPort; // declarations above.  Want to
 913  portSet   = &(port->PIO_SODR);            // burn a few cycles after
 914  portClear = &(port->PIO_CODR);            // starting timer to minimize
 915  timeValue = &(TC1->TC_CHANNEL[0].TC_CV);  // the initial 'while'.
 916  timeReset = &(TC1->TC_CHANNEL[0].TC_CCR);
 917  p         =  pixels;
 918  end       =  p + numBytes;
 919  pix       = *p++;
 920  mask      = 0x80;
 921
 922#ifdef NEO_KHZ400
 923  if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
 924#endif
 925    time0 = TIME_800_0;
 926    time1 = TIME_800_1;
 927    period = PERIOD_800;
 928#ifdef NEO_KHZ400
 929  } else { // 400 KHz bitstream
 930    time0 = TIME_400_0;
 931    time1 = TIME_400_1;
 932    period = PERIOD_400;
 933  }
 934#endif
 935
 936  for(t = time0;; t = time0) {
 937    if(pix & mask) t = time1;
 938    while(*timeValue < period);
 939    *portSet   = pinMask;
 940    *timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG;
 941    while(*timeValue < t);
 942    *portClear = pinMask;
 943    if(!(mask >>= 1)) {   // This 'inside-out' loop logic utilizes
 944      if(p >= end) break; // idle time to minimize inter-byte delays.
 945      pix = *p++;
 946      mask = 0x80;
 947    }
 948  }
 949  while(*timeValue < period); // Wait for last bit
 950  TC_Stop(TC1, 0);
 951
 952#endif // end Arduino Due
 953
 954#endif // end Architecture select
 955
 956  interrupts();
 957  endTime = micros(); // Save EOD time for latch on next call
 958}
 959
 960// Set the output pin number
 961void MitovEmbedded_Adafruit_NeoPixel::setPin(uint8_t p) {
 962  pinMode(pin, INPUT);
 963  pin = p;
 964  pinMode(p, OUTPUT);
 965  digitalWrite(p, LOW);
 966#ifdef __AVR__
 967  port    = portOutputRegister(digitalPinToPort(p));
 968  pinMask = digitalPinToBitMask(p);
 969#endif
 970}
 971
 972// Set pixel color from separate R,G,B components:
 973void MitovEmbedded_Adafruit_NeoPixel::setPixelColor(
 974 uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
 975  if(n < numLEDs) {
 976    if(brightness) { // See notes in setBrightness()
 977      r = (r * brightness) >> 8;
 978      g = (g * brightness) >> 8;
 979      b = (b * brightness) >> 8;
 980    }
 981    uint8_t *p = &pixels[n * 3];
 982    p[rOffset] = r;
 983    p[gOffset] = g;
 984    p[bOffset] = b;
 985  }
 986}
 987
 988// Set pixel color from 'packed' 32-bit RGB color:
 989void MitovEmbedded_Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
 990  if(n < numLEDs) {
 991    uint8_t
 992      r = (uint8_t)(c >> 16),
 993      g = (uint8_t)(c >>  8),
 994      b = (uint8_t)c;
 995    if(brightness) { // See notes in setBrightness()
 996      r = (r * brightness) >> 8;
 997      g = (g * brightness) >> 8;
 998      b = (b * brightness) >> 8;
 999    }
1000    uint8_t *p = &pixels[n * 3];
1001    p[rOffset] = r;
1002    p[gOffset] = g;
1003    p[bOffset] = b;
1004  }
1005}
1006
1007// Convert separate R,G,B into packed 32-bit RGB color.
1008// Packed format is always RGB, regardless of LED strand color order.
1009uint32_t MitovEmbedded_Adafruit_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) {
1010  return ((uint32_t)r << 16) | ((uint32_t)g <<  8) | b;
1011}
1012
1013// Query color from previously-set pixel (returns packed 32-bit RGB value)
1014uint32_t MitovEmbedded_Adafruit_NeoPixel::getPixelColor(uint16_t n) const {
1015  if(n >= numLEDs) {
1016    // Out of bounds, return no color.
1017    return 0;
1018  }
1019  uint8_t *p = &pixels[n * 3];
1020  uint32_t c = ((uint32_t)p[rOffset] << 16) |
1021               ((uint32_t)p[gOffset] <<  8) |
1022                (uint32_t)p[bOffset];
1023  // Adjust this back up to the true color, as setting a pixel color will
1024  // scale it back down again.
1025  if(brightness) { // See notes in setBrightness()
1026    //Cast the color to a byte array
1027    uint8_t * c_ptr =reinterpret_cast<uint8_t*>(&c);
1028    c_ptr[0] = (c_ptr[0] << 8)/brightness;
1029    c_ptr[1] = (c_ptr[1] << 8)/brightness;
1030    c_ptr[2] = (c_ptr[2] << 8)/brightness;
1031  }
1032  return c; // Pixel # is out of bounds
1033}
1034
1035// Returns pointer to pixels[] array.  Pixel data is stored in device-
1036// native format and is not translated here.  Application will need to be
1037// aware whether pixels are RGB vs. GRB and handle colors appropriately.
1038uint8_t *MitovEmbedded_Adafruit_NeoPixel::getPixels(void) const {
1039  return pixels;
1040}
1041
1042uint16_t MitovEmbedded_Adafruit_NeoPixel::numPixels(void) const {
1043  return numLEDs;
1044}
1045
1046// Adjust output brightness; 0=darkest (off), 255=brightest.  This does
1047// NOT immediately affect what's currently displayed on the LEDs.  The
1048// next call to show() will refresh the LEDs at this level.  However,
1049// this process is potentially "lossy," especially when increasing
1050// brightness.  The tight timing in the WS2811/WS2812 code means there
1051// aren't enough free cycles to perform this scaling on the fly as data
1052// is issued.  So we make a pass through the existing color data in RAM
1053// and scale it (subsequent graphics commands also work at this
1054// brightness level).  If there's a significant step up in brightness,
1055// the limited number of steps (quantization) in the old data will be
1056// quite visible in the re-scaled version.  For a non-destructive
1057// change, you'll need to re-render the full strip data.  C'est la vie.
1058void MitovEmbedded_Adafruit_NeoPixel::setBrightness(uint8_t b) {
1059  // Stored brightness value is different than what's passed.
1060  // This simplifies the actual scaling math later, allowing a fast
1061  // 8x8-bit multiply and taking the MSB.  'brightness' is a uint8_t,
1062  // adding 1 here may (intentionally) roll over...so 0 = max brightness
1063  // (color values are interpreted literally; no scaling), 1 = min
1064  // brightness (off), 255 = just below max brightness.
1065  uint8_t newBrightness = b + 1;
1066  if(newBrightness != brightness) { // Compare against prior value
1067    // Brightness has changed -- re-scale existing data in RAM
1068    uint8_t  c,
1069            *ptr           = pixels,
1070             oldBrightness = brightness - 1; // De-wrap old brightness value
1071    uint16_t scale;
1072    if(oldBrightness == 0) scale = 0; // Avoid /0
1073    else if(b == 255) scale = 65535 / oldBrightness;
1074    else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
1075    for(uint16_t i=0; i<numBytes; i++) {
1076      c      = *ptr;
1077      *ptr++ = (c * scale) >> 8;
1078    }
1079    brightness = newBrightness;
1080  }
1081}
1082
1083//Return the brightness value
1084uint8_t MitovEmbedded_Adafruit_NeoPixel::getBrightness(void) const {
1085  return brightness - 1;
1086}
1087
1088void MitovEmbedded_Adafruit_NeoPixel::clear() {
1089  memset(pixels, 0, numBytes);
1090}
1091
1092#endif // ADAFRUIT_NEOPIXEL_H