A conversion of the excellent Adafruit WS2801 library for Arduino to work on mbed

Dependents:   WiFiDipCortex_Cheerlights

Committer:
SomeRandomBloke
Date:
Fri Mar 08 13:25:50 2013 +0000
Revision:
1:6ff477690983
Parent:
0:582e1b9c1cc1
Child:
2:2fdaa13896a4
cleanup

Who changed what in which revision?

UserRevisionLine numberNew contents of line
SomeRandomBloke 0:582e1b9c1cc1 1 #include "mbed.h"
SomeRandomBloke 0:582e1b9c1cc1 2 #include "Adafruit_WS2801.h"
SomeRandomBloke 0:582e1b9c1cc1 3
SomeRandomBloke 0:582e1b9c1cc1 4 // Example to control WS2801-based RGB LED Modules in a strand or strip
SomeRandomBloke 0:582e1b9c1cc1 5 // Written by Adafruit - MIT license
SomeRandomBloke 0:582e1b9c1cc1 6 /*****************************************************************************/
SomeRandomBloke 0:582e1b9c1cc1 7
SomeRandomBloke 0:582e1b9c1cc1 8 // Constructor for use with hardware SPI (specific clock/data pins):
SomeRandomBloke 1:6ff477690983 9 //Adafruit_WS2801::Adafruit_WS2801(uint16_t n, uint8_t order): clkpin(PTD4), datapin(PTA12)
SomeRandomBloke 1:6ff477690983 10 //{
SomeRandomBloke 1:6ff477690983 11 // rgb_order = order;
SomeRandomBloke 1:6ff477690983 12 // alloc(n);
SomeRandomBloke 1:6ff477690983 13 // updatePins();
SomeRandomBloke 1:6ff477690983 14 //}
SomeRandomBloke 0:582e1b9c1cc1 15
SomeRandomBloke 0:582e1b9c1cc1 16 // Constructor for use with arbitrary clock/data pins:
SomeRandomBloke 0:582e1b9c1cc1 17 Adafruit_WS2801::Adafruit_WS2801(uint16_t n, PinName dpin, PinName cpin, uint8_t order) : clkpin(cpin), datapin(dpin)
SomeRandomBloke 0:582e1b9c1cc1 18 {
SomeRandomBloke 0:582e1b9c1cc1 19 rgb_order = order;
SomeRandomBloke 0:582e1b9c1cc1 20 alloc(n);
SomeRandomBloke 0:582e1b9c1cc1 21
SomeRandomBloke 0:582e1b9c1cc1 22 // updatePins(dpin, cpin);
SomeRandomBloke 0:582e1b9c1cc1 23 }
SomeRandomBloke 0:582e1b9c1cc1 24
SomeRandomBloke 0:582e1b9c1cc1 25 // Constructor for use with a matrix configuration, specify w, h for size of matrix
SomeRandomBloke 0:582e1b9c1cc1 26 // assumes configuration where string starts at coordinate 0,0 and continues to w-1,0, w-1,1
SomeRandomBloke 0:582e1b9c1cc1 27 // and on to 0,1, 0,2 and on to w-1,2 and so on. Snaking back and forth till the end.
SomeRandomBloke 0:582e1b9c1cc1 28 // other function calls with provide access to pixels via an x,y coordinate system
SomeRandomBloke 0:582e1b9c1cc1 29 Adafruit_WS2801::Adafruit_WS2801(uint16_t w, uint16_t h, PinName dpin, PinName cpin, uint8_t order) : clkpin(cpin), datapin(dpin)
SomeRandomBloke 0:582e1b9c1cc1 30 {
SomeRandomBloke 0:582e1b9c1cc1 31 rgb_order = order;
SomeRandomBloke 0:582e1b9c1cc1 32 alloc(w * h);
SomeRandomBloke 0:582e1b9c1cc1 33 width = w;
SomeRandomBloke 0:582e1b9c1cc1 34 height = h;
SomeRandomBloke 0:582e1b9c1cc1 35 // updatePins(dpin, cpin);
SomeRandomBloke 0:582e1b9c1cc1 36 }
SomeRandomBloke 0:582e1b9c1cc1 37
SomeRandomBloke 0:582e1b9c1cc1 38 // Allocate 3 bytes per pixel, init to RGB 'off' state:
SomeRandomBloke 0:582e1b9c1cc1 39 void Adafruit_WS2801::alloc(uint16_t n)
SomeRandomBloke 0:582e1b9c1cc1 40 {
SomeRandomBloke 0:582e1b9c1cc1 41 begun = false;
SomeRandomBloke 0:582e1b9c1cc1 42 numLEDs = ((pixels = (uint8_t *)calloc(n, 3)) != NULL) ? n : 0;
SomeRandomBloke 0:582e1b9c1cc1 43
SomeRandomBloke 0:582e1b9c1cc1 44 for(int bits = 0; bits <= numLEDs*24; bits++) {
SomeRandomBloke 0:582e1b9c1cc1 45 clkpin = 0;
SomeRandomBloke 0:582e1b9c1cc1 46 datapin = 0;
SomeRandomBloke 0:582e1b9c1cc1 47 clkpin = 1;
SomeRandomBloke 0:582e1b9c1cc1 48 }
SomeRandomBloke 0:582e1b9c1cc1 49 clkpin = 0;
SomeRandomBloke 0:582e1b9c1cc1 50 }
SomeRandomBloke 0:582e1b9c1cc1 51
SomeRandomBloke 0:582e1b9c1cc1 52 // via Michael Vogt/neophob: empty constructor is used when strand length
SomeRandomBloke 0:582e1b9c1cc1 53 // isn't known at compile-time; situations where program config might be
SomeRandomBloke 0:582e1b9c1cc1 54 // read from internal flash memory or an SD card, or arrive via serial
SomeRandomBloke 0:582e1b9c1cc1 55 // command. If using this constructor, MUST follow up with updateLength()
SomeRandomBloke 0:582e1b9c1cc1 56 // and updatePins() to establish the strand length and output pins!
SomeRandomBloke 0:582e1b9c1cc1 57 // Also, updateOrder() to change RGB vs GRB order (RGB is default).
SomeRandomBloke 1:6ff477690983 58 //Adafruit_WS2801::Adafruit_WS2801(void) : clkpin(PTD4), datapin(PTA12)
SomeRandomBloke 1:6ff477690983 59 //{
SomeRandomBloke 1:6ff477690983 60 // begun = false;
SomeRandomBloke 1:6ff477690983 61 // numLEDs = 0;
SomeRandomBloke 1:6ff477690983 62 // pixels = NULL;
SomeRandomBloke 1:6ff477690983 63 // rgb_order = WS2801_RGB;
SomeRandomBloke 1:6ff477690983 64 // updatePins(); // Must assume hardware SPI until pins are set
SomeRandomBloke 1:6ff477690983 65 //}
SomeRandomBloke 0:582e1b9c1cc1 66
SomeRandomBloke 0:582e1b9c1cc1 67 // Release memory (as needed):
SomeRandomBloke 0:582e1b9c1cc1 68 Adafruit_WS2801::~Adafruit_WS2801(void)
SomeRandomBloke 0:582e1b9c1cc1 69 {
SomeRandomBloke 0:582e1b9c1cc1 70 if (pixels != NULL) {
SomeRandomBloke 0:582e1b9c1cc1 71 free(pixels);
SomeRandomBloke 0:582e1b9c1cc1 72 }
SomeRandomBloke 0:582e1b9c1cc1 73 }
SomeRandomBloke 0:582e1b9c1cc1 74
SomeRandomBloke 0:582e1b9c1cc1 75 // Activate hard/soft SPI as appropriate:
SomeRandomBloke 0:582e1b9c1cc1 76 void Adafruit_WS2801::begin(void)
SomeRandomBloke 0:582e1b9c1cc1 77 {
SomeRandomBloke 0:582e1b9c1cc1 78
SomeRandomBloke 1:6ff477690983 79 datapin = 0;
SomeRandomBloke 1:6ff477690983 80 clkpin = 0;
SomeRandomBloke 0:582e1b9c1cc1 81 begun = true;
SomeRandomBloke 0:582e1b9c1cc1 82 }
SomeRandomBloke 0:582e1b9c1cc1 83
SomeRandomBloke 0:582e1b9c1cc1 84 // Change pin assignments post-constructor, switching to hardware SPI:
SomeRandomBloke 1:6ff477690983 85 /*
SomeRandomBloke 0:582e1b9c1cc1 86 void Adafruit_WS2801::updatePins(void)
SomeRandomBloke 0:582e1b9c1cc1 87 {
SomeRandomBloke 0:582e1b9c1cc1 88 hardwareSPI = true;
SomeRandomBloke 0:582e1b9c1cc1 89 datapin = 0;
SomeRandomBloke 0:582e1b9c1cc1 90 clkpin = 0;
SomeRandomBloke 0:582e1b9c1cc1 91 }
SomeRandomBloke 1:6ff477690983 92 */
SomeRandomBloke 0:582e1b9c1cc1 93
SomeRandomBloke 0:582e1b9c1cc1 94 // Change pin assignments post-constructor, using arbitrary pins:
SomeRandomBloke 1:6ff477690983 95 //void Adafruit_WS2801::updatePins(PinName dpin, PinName cpin)
SomeRandomBloke 1:6ff477690983 96 //{
SomeRandomBloke 0:582e1b9c1cc1 97 // Note: any prior clock/data pin directions are left as-is and are
SomeRandomBloke 0:582e1b9c1cc1 98 // NOT restored as inputs!
SomeRandomBloke 0:582e1b9c1cc1 99
SomeRandomBloke 1:6ff477690983 100 // datapin = DigitalOut(dpin);
SomeRandomBloke 1:6ff477690983 101 // clkpin = DigitalOut(cpin);
SomeRandomBloke 1:6ff477690983 102 //}
SomeRandomBloke 0:582e1b9c1cc1 103
SomeRandomBloke 0:582e1b9c1cc1 104 uint16_t Adafruit_WS2801::numPixels(void)
SomeRandomBloke 0:582e1b9c1cc1 105 {
SomeRandomBloke 0:582e1b9c1cc1 106 return numLEDs;
SomeRandomBloke 0:582e1b9c1cc1 107 }
SomeRandomBloke 0:582e1b9c1cc1 108
SomeRandomBloke 0:582e1b9c1cc1 109 // Change strand length (see notes with empty constructor, above):
SomeRandomBloke 0:582e1b9c1cc1 110 void Adafruit_WS2801::updateLength(uint16_t n)
SomeRandomBloke 0:582e1b9c1cc1 111 {
SomeRandomBloke 0:582e1b9c1cc1 112 if(pixels != NULL) free(pixels); // Free existing data (if any)
SomeRandomBloke 0:582e1b9c1cc1 113 // Allocate new data -- note: ALL PIXELS ARE CLEARED
SomeRandomBloke 0:582e1b9c1cc1 114 numLEDs = ((pixels = (uint8_t *)calloc(n, 3)) != NULL) ? n : 0;
SomeRandomBloke 0:582e1b9c1cc1 115 // 'begun' state does not change -- pins retain prior modes
SomeRandomBloke 0:582e1b9c1cc1 116 }
SomeRandomBloke 0:582e1b9c1cc1 117
SomeRandomBloke 0:582e1b9c1cc1 118 // Change RGB data order (see notes with empty constructor, above):
SomeRandomBloke 0:582e1b9c1cc1 119 void Adafruit_WS2801::updateOrder(uint8_t order)
SomeRandomBloke 0:582e1b9c1cc1 120 {
SomeRandomBloke 0:582e1b9c1cc1 121 rgb_order = order;
SomeRandomBloke 0:582e1b9c1cc1 122 // Existing LED data, if any, is NOT reformatted to new data order.
SomeRandomBloke 0:582e1b9c1cc1 123 // Calling function should clear or fill pixel data anew.
SomeRandomBloke 0:582e1b9c1cc1 124 }
SomeRandomBloke 0:582e1b9c1cc1 125
SomeRandomBloke 0:582e1b9c1cc1 126 void Adafruit_WS2801::show(void)
SomeRandomBloke 0:582e1b9c1cc1 127 {
SomeRandomBloke 0:582e1b9c1cc1 128 uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED
SomeRandomBloke 0:582e1b9c1cc1 129 uint8_t bit;
SomeRandomBloke 0:582e1b9c1cc1 130
SomeRandomBloke 0:582e1b9c1cc1 131 // Write 24 bits per pixel:
SomeRandomBloke 0:582e1b9c1cc1 132 for(i=0; i<nl3; i++ ) {
SomeRandomBloke 0:582e1b9c1cc1 133 for(bit=0x80; bit; bit >>= 1) {
SomeRandomBloke 0:582e1b9c1cc1 134 clkpin = 0;
SomeRandomBloke 0:582e1b9c1cc1 135 if(pixels[i] & bit) datapin = 1;
SomeRandomBloke 0:582e1b9c1cc1 136 else datapin = 0;
SomeRandomBloke 0:582e1b9c1cc1 137 clkpin = 1;
SomeRandomBloke 0:582e1b9c1cc1 138 }
SomeRandomBloke 0:582e1b9c1cc1 139 }
SomeRandomBloke 0:582e1b9c1cc1 140
SomeRandomBloke 1:6ff477690983 141 clkpin = 0;
SomeRandomBloke 0:582e1b9c1cc1 142 wait_ms(1); // Data is latched by holding clock pin low for 1 millisecond
SomeRandomBloke 1:6ff477690983 143 clkpin = 1;
SomeRandomBloke 0:582e1b9c1cc1 144 }
SomeRandomBloke 0:582e1b9c1cc1 145
SomeRandomBloke 0:582e1b9c1cc1 146 // Set pixel color from separate 8-bit R, G, B components:
SomeRandomBloke 0:582e1b9c1cc1 147 void Adafruit_WS2801::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
SomeRandomBloke 0:582e1b9c1cc1 148 {
SomeRandomBloke 0:582e1b9c1cc1 149 if(n < numLEDs) { // Arrays are 0-indexed, thus NOT '<='
SomeRandomBloke 0:582e1b9c1cc1 150 uint8_t *p = &pixels[n * 3];
SomeRandomBloke 0:582e1b9c1cc1 151 // See notes later regarding color order
SomeRandomBloke 0:582e1b9c1cc1 152 if(rgb_order == WS2801_RGB) {
SomeRandomBloke 0:582e1b9c1cc1 153 *p++ = r;
SomeRandomBloke 0:582e1b9c1cc1 154 *p++ = g;
SomeRandomBloke 0:582e1b9c1cc1 155 } else {
SomeRandomBloke 0:582e1b9c1cc1 156 *p++ = g;
SomeRandomBloke 0:582e1b9c1cc1 157 *p++ = r;
SomeRandomBloke 0:582e1b9c1cc1 158 }
SomeRandomBloke 0:582e1b9c1cc1 159 *p++ = b;
SomeRandomBloke 0:582e1b9c1cc1 160 }
SomeRandomBloke 0:582e1b9c1cc1 161 }
SomeRandomBloke 0:582e1b9c1cc1 162
SomeRandomBloke 0:582e1b9c1cc1 163 // Set pixel color from separate 8-bit R, G, B components using x,y coordinate system:
SomeRandomBloke 0:582e1b9c1cc1 164 void Adafruit_WS2801::setPixelColor(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
SomeRandomBloke 0:582e1b9c1cc1 165 {
SomeRandomBloke 0:582e1b9c1cc1 166 bool evenRow = ((y % 2) == 0);
SomeRandomBloke 0:582e1b9c1cc1 167 // calculate x offset first
SomeRandomBloke 0:582e1b9c1cc1 168 uint16_t offset = x % width;
SomeRandomBloke 0:582e1b9c1cc1 169 if (!evenRow) {
SomeRandomBloke 0:582e1b9c1cc1 170 offset = (width-1) - offset;
SomeRandomBloke 0:582e1b9c1cc1 171 }
SomeRandomBloke 0:582e1b9c1cc1 172 // add y offset
SomeRandomBloke 0:582e1b9c1cc1 173 offset += y * width;
SomeRandomBloke 0:582e1b9c1cc1 174 setPixelColor(offset, r, g, b);
SomeRandomBloke 0:582e1b9c1cc1 175 }
SomeRandomBloke 0:582e1b9c1cc1 176
SomeRandomBloke 0:582e1b9c1cc1 177 // Set pixel color from 'packed' 32-bit RGB value:
SomeRandomBloke 0:582e1b9c1cc1 178 void Adafruit_WS2801::setPixelColor(uint16_t n, uint32_t c)
SomeRandomBloke 0:582e1b9c1cc1 179 {
SomeRandomBloke 0:582e1b9c1cc1 180 if(n < numLEDs) { // Arrays are 0-indexed, thus NOT '<='
SomeRandomBloke 0:582e1b9c1cc1 181 uint8_t *p = &pixels[n * 3];
SomeRandomBloke 0:582e1b9c1cc1 182 // To keep the show() loop as simple & fast as possible, the
SomeRandomBloke 0:582e1b9c1cc1 183 // internal color representation is native to different pixel
SomeRandomBloke 0:582e1b9c1cc1 184 // types. For compatibility with existing code, 'packed' RGB
SomeRandomBloke 0:582e1b9c1cc1 185 // values passed in or out are always 0xRRGGBB order.
SomeRandomBloke 0:582e1b9c1cc1 186 if(rgb_order == WS2801_RGB) {
SomeRandomBloke 0:582e1b9c1cc1 187 *p++ = c >> 16; // Red
SomeRandomBloke 0:582e1b9c1cc1 188 *p++ = c >> 8; // Green
SomeRandomBloke 0:582e1b9c1cc1 189 } else {
SomeRandomBloke 0:582e1b9c1cc1 190 *p++ = c >> 8; // Green
SomeRandomBloke 0:582e1b9c1cc1 191 *p++ = c >> 16; // Red
SomeRandomBloke 0:582e1b9c1cc1 192 }
SomeRandomBloke 0:582e1b9c1cc1 193 *p++ = c; // Blue
SomeRandomBloke 0:582e1b9c1cc1 194 }
SomeRandomBloke 0:582e1b9c1cc1 195 }
SomeRandomBloke 0:582e1b9c1cc1 196
SomeRandomBloke 0:582e1b9c1cc1 197 // Set pixel color from 'packed' 32-bit RGB value using x,y coordinate system:
SomeRandomBloke 0:582e1b9c1cc1 198 void Adafruit_WS2801::setPixelColor(uint16_t x, uint16_t y, uint32_t c)
SomeRandomBloke 0:582e1b9c1cc1 199 {
SomeRandomBloke 0:582e1b9c1cc1 200 bool evenRow = ((y % 2) == 0);
SomeRandomBloke 0:582e1b9c1cc1 201 // calculate x offset first
SomeRandomBloke 0:582e1b9c1cc1 202 uint16_t offset = x % width;
SomeRandomBloke 0:582e1b9c1cc1 203 if (!evenRow) {
SomeRandomBloke 0:582e1b9c1cc1 204 offset = (width-1) - offset;
SomeRandomBloke 0:582e1b9c1cc1 205 }
SomeRandomBloke 0:582e1b9c1cc1 206 // add y offset
SomeRandomBloke 0:582e1b9c1cc1 207 offset += y * width;
SomeRandomBloke 0:582e1b9c1cc1 208 setPixelColor(offset, c);
SomeRandomBloke 0:582e1b9c1cc1 209 }
SomeRandomBloke 0:582e1b9c1cc1 210
SomeRandomBloke 0:582e1b9c1cc1 211 // Query color from previously-set pixel (returns packed 32-bit RGB value)
SomeRandomBloke 0:582e1b9c1cc1 212 uint32_t Adafruit_WS2801::getPixelColor(uint16_t n)
SomeRandomBloke 0:582e1b9c1cc1 213 {
SomeRandomBloke 0:582e1b9c1cc1 214 if(n < numLEDs) {
SomeRandomBloke 0:582e1b9c1cc1 215 uint16_t ofs = n * 3;
SomeRandomBloke 0:582e1b9c1cc1 216 // To keep the show() loop as simple & fast as possible, the
SomeRandomBloke 0:582e1b9c1cc1 217 // internal color representation is native to different pixel
SomeRandomBloke 0:582e1b9c1cc1 218 // types. For compatibility with existing code, 'packed' RGB
SomeRandomBloke 0:582e1b9c1cc1 219 // values passed in or out are always 0xRRGGBB order.
SomeRandomBloke 0:582e1b9c1cc1 220 return (rgb_order == WS2801_RGB) ?
SomeRandomBloke 0:582e1b9c1cc1 221 ((uint32_t)pixels[ofs] << 16) | ((uint16_t) pixels[ofs + 1] << 8) | pixels[ofs + 2] :
SomeRandomBloke 0:582e1b9c1cc1 222 (pixels[ofs] << 8) | ((uint32_t)pixels[ofs + 1] << 16) | pixels[ofs + 2];
SomeRandomBloke 0:582e1b9c1cc1 223 }
SomeRandomBloke 0:582e1b9c1cc1 224
SomeRandomBloke 0:582e1b9c1cc1 225 return 0; // Pixel # is out of bounds
SomeRandomBloke 0:582e1b9c1cc1 226 }