ws2812b sample firmware.

Dependencies:   BurstSPI

Dependents:   mbed_ws2812b mbed_ws2812b

Fork of PixelArray by Jacob Bramley

neopixel-spi.cpp

Committer:
JacobBramley
Date:
2014-07-24
Revision:
0:38eeab21a162
Child:
1:adbbe3e9f2c5

File content as of revision 0:38eeab21a162:

#include <stdint.h>
#include "mbed.h"
#include "neopixel-spi.h"

namespace neopixel {

Array::Array(PinName out) : spi_(out, NC, NC) {
  // TODO: WS2811 has a different timing specification.
  
  // WS2812 bit timings:
  //  '0': ----________    mark: 0.40us, space: 0.85us
  //  '1': --------____    mark: 0.80us, space: 0.45us
  // The period is 1.25us, giving a basic frequency of 800kHz.
  // Using three SPI bits per NeoPixel bit, we need an API frequency of 2.4MHz.
  //  '0': 100             mark: 0.42us, space: 0.83us
  //  '1': 110             mark: 0.83us, space: 0.42us
  // These timings are well within the +/-150ns tolerance specified by WS2812.
  
  spi_.frequency(2400000);
  spi_.format(12);          // Send four NeoPixel bits in each packet.
}

static void SendFourBits(BurstSPI& spi, uint32_t bits) {
  static int const pattern_width = 3;
  uint32_t word = 04444;  // 0b100100100100
  
  for (int i = 0; i < 4; i++) {
    word |= ((bits >> 3) & 1) << (pattern_width * i + 1);
  }
  
  spi.fastWrite(word);
}

void Array::Update(Pixel buffer[], size_t length) {
  // Pixels are sent as follows:
  // - The first transmitted pixel is the pixel closest to the transmitter.
  // - The most significant bit is always sent first.
  // - Green is sent first, then red, then blue.
  //
  // g7,g6,g5,g4,g3,g2,g1,g0,r7,r6,r5,r4,r3,r2,r1,r0,b7,b6,b5,b4,b3,b2,b1,b0
  // \                                                                     /
  //  \___________________________________________________________________/
  //                           |
  //                          GRB,GRB,GRB,GRB,...
  
  for (size_t i = 0; i < length; i++) {
    SendFourBits(spi_, (buffer[i].green >> 4) & 0xf);
    SendFourBits(spi_, (buffer[i].green >> 0) & 0xf);
    SendFourBits(spi_, (buffer[i].red >> 4) & 0xf);
    SendFourBits(spi_, (buffer[i].red >> 0) & 0xf);
    SendFourBits(spi_, (buffer[i].blue >> 4) & 0xf);
    SendFourBits(spi_, (buffer[i].blue >> 0) & 0xf);
  }
  spi_.clearRX();
  
  wait_us(50);
}

}