Adafruit Neopixel Library [PORTED]

It’s not pretty yet, but it’s working! Just a proof of concept that it can be done, pretty easily too:

(EDIT: see my next post for the port I made of adafruit’s library for the spark core on github)

Code:

uint32_t rgb;
uint16_t neoPin = D0;

void setPixel(uint32_t grb) {
  uint8_t i;

  uint8_t grb_bit = 23;
  uint32_t grb_mask = 0x00800000;

  for (i = 0; i < 24; i++) {
    if (grb & (1 << grb_bit)) {
      // 700ns HIGH (meas. 680ns)
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH

      // 600ns LOW (meas. 612ns)
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
    } else {
      // 350ns HIGH (meas. 348ns)
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
      PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH

      // 800ns LOW (meas. 808ns)
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
      PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
    }
    grb_bit--;
    grb_mask = grb_mask >> 1;
  }
}

// Packs and sets a 32-bit color from individual colors
void setRGB(uint8_t red, uint8_t green, uint8_t blue) {
  uint32_t grb = ((uint32_t) red << 16) + ((uint32_t) green << 16) + blue;
  setPixel(grb);
}

// Reorders and sets a 32-bit packed color
void setColor(uint32_t color) {
  uint32_t grb = ((uint32_t)(color >> 8) & 0x0000FF00) + (uint32_t)((color << 8) & 0x00FF0000) + (uint32_t)(color & 0x000000FF);
  setPixel(grb);
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t j;

  for (j = 0; j < 256; j++) { // 1 cycle of all colors on wheel
    setColor(Wheel(j));
    delayMicroseconds(wait * 1000);
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(uint8_t WheelPos) {
  if (WheelPos < 85) {
    return packColor(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return packColor(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return packColor(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

// Convert separate R,G,B into packed 32-bit RGB color.
// Packed format is always RGB, regardless of LED strand color order.
uint32_t packColor(uint8_t r, uint8_t g, uint8_t b) {
  uint32_t rgb = (((uint32_t) r << 16) + ((uint32_t) g << 8) + b);
  return rgb;
}

void setup() {
  pinMode(neoPin, OUTPUT);
}

void loop() {
  rgb = 0x00000FF;
  //setColor(rgb);

  rainbowCycle(20);
}

As you can see, I didn’t spend a lot of time on the “timing” part… running the bit-banging part over and over again was a dirty way to do it. However it works well as you can see from the measured timing and demo. I think there are little glitches every no and then because of interrupts that should probably be turned off during the critical timing… or, driving at 3.3V. I seem to recall this 3.3V issue before was the reason it was a tad glitchy.

If anyone can point me a better way to burn 1 cycle, please let me know. I tried Nop(); and nop(); to no avail.

Anyhoo, I said I’d keep you up to date on anything that’s happening… so you got it! Down and dirty.

5 Likes