A conversion of the excellent Adafruit WS2801 library for Arduino to work on mbed
Adafruit_WS2801.cpp@4:987c91c45188, 2014-06-03 (annotated)
- Committer:
- SomeRandomBloke
- Date:
- Tue Jun 03 20:19:23 2014 +0000
- Revision:
- 4:987c91c45188
- Parent:
- 3:dfffbd9f8ac6
- Child:
- 5:bbe85db83246
re-added delay on hardware spi as not working fully without it
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
SomeRandomBloke | 0:582e1b9c1cc1 | 1 | #include "mbed.h" |
SomeRandomBloke | 0:582e1b9c1cc1 | 2 | #include "Adafruit_WS2801.h" |
SomeRandomBloke | 0:582e1b9c1cc1 | 3 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 4 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 5 | // Example to control WS2801-based RGB LED Modules in a strand or strip |
SomeRandomBloke | 0:582e1b9c1cc1 | 6 | // Written by Adafruit - MIT license |
SomeRandomBloke | 0:582e1b9c1cc1 | 7 | /*****************************************************************************/ |
SomeRandomBloke | 0:582e1b9c1cc1 | 8 | |
SomeRandomBloke | 2:2fdaa13896a4 | 9 | SPI spi(p16, p15, p13); // mosi, miso, sclk |
SomeRandomBloke | 2:2fdaa13896a4 | 10 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 11 | // Constructor for use with hardware SPI (specific clock/data pins): |
SomeRandomBloke | 3:dfffbd9f8ac6 | 12 | /*Adafruit_WS2801::Adafruit_WS2801(uint16_t n, uint8_t order): clkpin(PTD4), datapin(PTA12) |
SomeRandomBloke | 0:582e1b9c1cc1 | 13 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 14 | rgb_order = order; |
SomeRandomBloke | 0:582e1b9c1cc1 | 15 | alloc(n); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 16 | updatePins(); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 17 | }*/ |
SomeRandomBloke | 3:dfffbd9f8ac6 | 18 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 19 | // Constructor for use with arbitrary clock/data pins: |
SomeRandomBloke | 3:dfffbd9f8ac6 | 20 | Adafruit_WS2801::Adafruit_WS2801(int16_t n, PinName dpin, PinName cpin, uint8_t order) |
SomeRandomBloke | 3:dfffbd9f8ac6 | 21 | : clkpin(cpin), datapin(dpin) |
SomeRandomBloke | 3:dfffbd9f8ac6 | 22 | { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 23 | rgb_order = order; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 24 | alloc(n); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 25 | width = 1; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 26 | height = n; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 27 | hardwareSPI = false; |
SomeRandomBloke | 0:582e1b9c1cc1 | 28 | // updatePins(dpin, cpin); |
SomeRandomBloke | 0:582e1b9c1cc1 | 29 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 30 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 31 | // Constructor for use with a matrix configuration, specify w, h for size of matrix |
SomeRandomBloke | 0:582e1b9c1cc1 | 32 | // assumes configuration where string starts at coordinate 0,0 and continues to w-1,0, w-1,1 |
SomeRandomBloke | 0:582e1b9c1cc1 | 33 | // 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 | 34 | // other function calls with provide access to pixels via an x,y coordinate system |
SomeRandomBloke | 3:dfffbd9f8ac6 | 35 | Adafruit_WS2801::Adafruit_WS2801(int16_t w, int16_t h, PinName dpin, PinName cpin, uint8_t order) |
SomeRandomBloke | 3:dfffbd9f8ac6 | 36 | : clkpin(cpin), datapin(dpin) |
SomeRandomBloke | 0:582e1b9c1cc1 | 37 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 38 | rgb_order = order; |
SomeRandomBloke | 0:582e1b9c1cc1 | 39 | alloc(w * h); |
SomeRandomBloke | 0:582e1b9c1cc1 | 40 | width = w; |
SomeRandomBloke | 0:582e1b9c1cc1 | 41 | height = h; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 42 | hardwareSPI = false; |
SomeRandomBloke | 0:582e1b9c1cc1 | 43 | // updatePins(dpin, cpin); |
SomeRandomBloke | 0:582e1b9c1cc1 | 44 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 45 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 46 | // Allocate 3 bytes per pixel, init to RGB 'off' state: |
SomeRandomBloke | 0:582e1b9c1cc1 | 47 | void Adafruit_WS2801::alloc(uint16_t n) |
SomeRandomBloke | 0:582e1b9c1cc1 | 48 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 49 | begun = false; |
SomeRandomBloke | 0:582e1b9c1cc1 | 50 | numLEDs = ((pixels = (uint8_t *)calloc(n, 3)) != NULL) ? n : 0; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 51 | hardwareSPI = true; |
SomeRandomBloke | 2:2fdaa13896a4 | 52 | |
SomeRandomBloke | 2:2fdaa13896a4 | 53 | // for(int bits = 0; bits <= numLEDs*24; bits++) { |
SomeRandomBloke | 2:2fdaa13896a4 | 54 | // spi.write(0x00); |
SomeRandomBloke | 2:2fdaa13896a4 | 55 | // clkpin = 0; |
SomeRandomBloke | 2:2fdaa13896a4 | 56 | // datapin = 0; |
SomeRandomBloke | 2:2fdaa13896a4 | 57 | // clkpin = 1; |
SomeRandomBloke | 2:2fdaa13896a4 | 58 | // } |
SomeRandomBloke | 2:2fdaa13896a4 | 59 | // clkpin = 0; |
SomeRandomBloke | 0:582e1b9c1cc1 | 60 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 61 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 62 | // Constructor for use with a matrix configuration, specify w, h for size of matrix |
SomeRandomBloke | 3:dfffbd9f8ac6 | 63 | // assumes configuration where string starts at coordinate 0,0 and continues to w-1,0, w-1,1 |
SomeRandomBloke | 3:dfffbd9f8ac6 | 64 | // and on to 0,1, 0,2 and on to w-1,2 and so on. Snaking back and forth till the end. |
SomeRandomBloke | 3:dfffbd9f8ac6 | 65 | // other function calls with provide access to pixels via an x,y coordinate system |
SomeRandomBloke | 3:dfffbd9f8ac6 | 66 | /*Adafruit_WS2801::Adafruit_WS2801(uint16_t w, uint16_t h, uint8_t order) |
SomeRandomBloke | 3:dfffbd9f8ac6 | 67 | { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 68 | rgb_order = order; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 69 | alloc(w * h); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 70 | width = w; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 71 | height = h; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 72 | hardwareSPI = true; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 73 | // updatePins(dpin, cpin); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 74 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 75 | */ |
SomeRandomBloke | 3:dfffbd9f8ac6 | 76 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 77 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 78 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 79 | // via Michael Vogt/neophob: empty constructor is used when strand length |
SomeRandomBloke | 0:582e1b9c1cc1 | 80 | // isn't known at compile-time; situations where program config might be |
SomeRandomBloke | 0:582e1b9c1cc1 | 81 | // read from internal flash memory or an SD card, or arrive via serial |
SomeRandomBloke | 0:582e1b9c1cc1 | 82 | // command. If using this constructor, MUST follow up with updateLength() |
SomeRandomBloke | 0:582e1b9c1cc1 | 83 | // and updatePins() to establish the strand length and output pins! |
SomeRandomBloke | 0:582e1b9c1cc1 | 84 | // Also, updateOrder() to change RGB vs GRB order (RGB is default). |
SomeRandomBloke | 1:6ff477690983 | 85 | //Adafruit_WS2801::Adafruit_WS2801(void) : clkpin(PTD4), datapin(PTA12) |
SomeRandomBloke | 1:6ff477690983 | 86 | //{ |
SomeRandomBloke | 1:6ff477690983 | 87 | // begun = false; |
SomeRandomBloke | 1:6ff477690983 | 88 | // numLEDs = 0; |
SomeRandomBloke | 1:6ff477690983 | 89 | // pixels = NULL; |
SomeRandomBloke | 1:6ff477690983 | 90 | // rgb_order = WS2801_RGB; |
SomeRandomBloke | 1:6ff477690983 | 91 | // updatePins(); // Must assume hardware SPI until pins are set |
SomeRandomBloke | 1:6ff477690983 | 92 | //} |
SomeRandomBloke | 0:582e1b9c1cc1 | 93 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 94 | // Release memory (as needed): |
SomeRandomBloke | 0:582e1b9c1cc1 | 95 | Adafruit_WS2801::~Adafruit_WS2801(void) |
SomeRandomBloke | 0:582e1b9c1cc1 | 96 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 97 | if (pixels != NULL) { |
SomeRandomBloke | 0:582e1b9c1cc1 | 98 | free(pixels); |
SomeRandomBloke | 0:582e1b9c1cc1 | 99 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 100 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 101 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 102 | // Activate hard/soft SPI as appropriate: |
SomeRandomBloke | 0:582e1b9c1cc1 | 103 | void Adafruit_WS2801::begin(void) |
SomeRandomBloke | 0:582e1b9c1cc1 | 104 | { |
SomeRandomBloke | 2:2fdaa13896a4 | 105 | if( hardwareSPI ) { |
SomeRandomBloke | 2:2fdaa13896a4 | 106 | // Setup the spi for 8 bit data, high steady state clock, |
SomeRandomBloke | 2:2fdaa13896a4 | 107 | // second edge capture, with a 1MHz clock rate |
SomeRandomBloke | 2:2fdaa13896a4 | 108 | spi.format(8,0); |
SomeRandomBloke | 2:2fdaa13896a4 | 109 | spi.frequency(1000000); |
SomeRandomBloke | 2:2fdaa13896a4 | 110 | } else { |
SomeRandomBloke | 2:2fdaa13896a4 | 111 | datapin = 0; |
SomeRandomBloke | 2:2fdaa13896a4 | 112 | clkpin = 0; |
SomeRandomBloke | 2:2fdaa13896a4 | 113 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 114 | begun = true; |
SomeRandomBloke | 0:582e1b9c1cc1 | 115 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 116 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 117 | // Change pin assignments post-constructor, switching to hardware SPI: |
SomeRandomBloke | 0:582e1b9c1cc1 | 118 | void Adafruit_WS2801::updatePins(void) |
SomeRandomBloke | 0:582e1b9c1cc1 | 119 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 120 | hardwareSPI = true; |
SomeRandomBloke | 0:582e1b9c1cc1 | 121 | datapin = 0; |
SomeRandomBloke | 0:582e1b9c1cc1 | 122 | clkpin = 0; |
SomeRandomBloke | 0:582e1b9c1cc1 | 123 | } |
SomeRandomBloke | 2:2fdaa13896a4 | 124 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 125 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 126 | // Change pin assignments post-constructor, using arbitrary pins: |
SomeRandomBloke | 3:dfffbd9f8ac6 | 127 | void Adafruit_WS2801::updatePins(PinName dpin, PinName cpin) |
SomeRandomBloke | 3:dfffbd9f8ac6 | 128 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 129 | // Note: any prior clock/data pin directions are left as-is and are |
SomeRandomBloke | 0:582e1b9c1cc1 | 130 | // NOT restored as inputs! |
SomeRandomBloke | 0:582e1b9c1cc1 | 131 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 132 | datapin = DigitalOut(dpin); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 133 | clkpin = DigitalOut(cpin); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 134 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 135 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 136 | // Return the number of LEDs |
SomeRandomBloke | 0:582e1b9c1cc1 | 137 | uint16_t Adafruit_WS2801::numPixels(void) |
SomeRandomBloke | 0:582e1b9c1cc1 | 138 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 139 | return numLEDs; |
SomeRandomBloke | 0:582e1b9c1cc1 | 140 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 141 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 142 | // Change strand length (see notes with empty constructor, above): |
SomeRandomBloke | 0:582e1b9c1cc1 | 143 | void Adafruit_WS2801::updateLength(uint16_t n) |
SomeRandomBloke | 0:582e1b9c1cc1 | 144 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 145 | if(pixels != NULL) free(pixels); // Free existing data (if any) |
SomeRandomBloke | 0:582e1b9c1cc1 | 146 | // Allocate new data -- note: ALL PIXELS ARE CLEARED |
SomeRandomBloke | 0:582e1b9c1cc1 | 147 | numLEDs = ((pixels = (uint8_t *)calloc(n, 3)) != NULL) ? n : 0; |
SomeRandomBloke | 0:582e1b9c1cc1 | 148 | // 'begun' state does not change -- pins retain prior modes |
SomeRandomBloke | 0:582e1b9c1cc1 | 149 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 150 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 151 | // Change RGB data order (see notes with empty constructor, above): |
SomeRandomBloke | 0:582e1b9c1cc1 | 152 | void Adafruit_WS2801::updateOrder(uint8_t order) |
SomeRandomBloke | 0:582e1b9c1cc1 | 153 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 154 | rgb_order = order; |
SomeRandomBloke | 0:582e1b9c1cc1 | 155 | // Existing LED data, if any, is NOT reformatted to new data order. |
SomeRandomBloke | 0:582e1b9c1cc1 | 156 | // Calling function should clear or fill pixel data anew. |
SomeRandomBloke | 0:582e1b9c1cc1 | 157 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 158 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 159 | void Adafruit_WS2801::show(void) |
SomeRandomBloke | 0:582e1b9c1cc1 | 160 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 161 | uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED |
SomeRandomBloke | 2:2fdaa13896a4 | 162 | |
SomeRandomBloke | 2:2fdaa13896a4 | 163 | if( hardwareSPI ) { |
SomeRandomBloke | 2:2fdaa13896a4 | 164 | for(i=0; i<nl3; i++ ) { |
SomeRandomBloke | 2:2fdaa13896a4 | 165 | spi.write( pixels[i]); |
SomeRandomBloke | 2:2fdaa13896a4 | 166 | } |
SomeRandomBloke | 4:987c91c45188 | 167 | wait_ms(1); // Needed otherwise sometimes doesnt display |
SomeRandomBloke | 2:2fdaa13896a4 | 168 | } else { |
SomeRandomBloke | 2:2fdaa13896a4 | 169 | uint8_t bit; |
SomeRandomBloke | 0:582e1b9c1cc1 | 170 | |
SomeRandomBloke | 2:2fdaa13896a4 | 171 | // Write 24 bits per pixel: |
SomeRandomBloke | 2:2fdaa13896a4 | 172 | for(i=0; i<nl3; i++ ) { |
SomeRandomBloke | 2:2fdaa13896a4 | 173 | for(bit=0x80; bit; bit >>= 1) { |
SomeRandomBloke | 2:2fdaa13896a4 | 174 | clkpin = 0; |
SomeRandomBloke | 2:2fdaa13896a4 | 175 | datapin = (pixels[i] & bit) ? 1 : 0; |
SomeRandomBloke | 2:2fdaa13896a4 | 176 | clkpin = 1; |
SomeRandomBloke | 2:2fdaa13896a4 | 177 | wait_us(100); |
SomeRandomBloke | 2:2fdaa13896a4 | 178 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 179 | } |
SomeRandomBloke | 2:2fdaa13896a4 | 180 | datapin = 0; |
SomeRandomBloke | 0:582e1b9c1cc1 | 181 | |
SomeRandomBloke | 2:2fdaa13896a4 | 182 | clkpin = 0; |
SomeRandomBloke | 2:2fdaa13896a4 | 183 | wait_ms(1); // Data is latched by holding clock pin low for 1 millisecond |
SomeRandomBloke | 2:2fdaa13896a4 | 184 | clkpin = 1; |
SomeRandomBloke | 2:2fdaa13896a4 | 185 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 186 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 187 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 188 | // Set pixel color from separate 8-bit R, G, B components: |
SomeRandomBloke | 0:582e1b9c1cc1 | 189 | void Adafruit_WS2801::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) |
SomeRandomBloke | 0:582e1b9c1cc1 | 190 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 191 | if(n < numLEDs) { // Arrays are 0-indexed, thus NOT '<=' |
SomeRandomBloke | 0:582e1b9c1cc1 | 192 | uint8_t *p = &pixels[n * 3]; |
SomeRandomBloke | 0:582e1b9c1cc1 | 193 | // See notes later regarding color order |
SomeRandomBloke | 0:582e1b9c1cc1 | 194 | if(rgb_order == WS2801_RGB) { |
SomeRandomBloke | 0:582e1b9c1cc1 | 195 | *p++ = r; |
SomeRandomBloke | 0:582e1b9c1cc1 | 196 | *p++ = g; |
SomeRandomBloke | 0:582e1b9c1cc1 | 197 | } else { |
SomeRandomBloke | 0:582e1b9c1cc1 | 198 | *p++ = g; |
SomeRandomBloke | 0:582e1b9c1cc1 | 199 | *p++ = r; |
SomeRandomBloke | 0:582e1b9c1cc1 | 200 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 201 | *p++ = b; |
SomeRandomBloke | 0:582e1b9c1cc1 | 202 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 203 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 204 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 205 | // Set pixel color from separate 8-bit R, G, B components using x,y coordinate system: |
SomeRandomBloke | 3:dfffbd9f8ac6 | 206 | void Adafruit_WS2801::setPixelColor(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b) |
SomeRandomBloke | 0:582e1b9c1cc1 | 207 | { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 208 | if( x < 0 || x >= width || y < 0 || y >= height ) |
SomeRandomBloke | 3:dfffbd9f8ac6 | 209 | return; // Dont try to update a pixel that doesnt exist |
SomeRandomBloke | 3:dfffbd9f8ac6 | 210 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 211 | bool evenRow = ((y % 2) == 0); |
SomeRandomBloke | 0:582e1b9c1cc1 | 212 | // calculate x offset first |
SomeRandomBloke | 0:582e1b9c1cc1 | 213 | uint16_t offset = x % width; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 214 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 215 | if (!evenRow) { |
SomeRandomBloke | 0:582e1b9c1cc1 | 216 | offset = (width-1) - offset; |
SomeRandomBloke | 0:582e1b9c1cc1 | 217 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 218 | // add y offset |
SomeRandomBloke | 0:582e1b9c1cc1 | 219 | offset += y * width; |
SomeRandomBloke | 0:582e1b9c1cc1 | 220 | setPixelColor(offset, r, g, b); |
SomeRandomBloke | 0:582e1b9c1cc1 | 221 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 222 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 223 | // Set pixel color from 'packed' 32-bit RGB value: |
SomeRandomBloke | 0:582e1b9c1cc1 | 224 | void Adafruit_WS2801::setPixelColor(uint16_t n, uint32_t c) |
SomeRandomBloke | 0:582e1b9c1cc1 | 225 | { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 226 | if( n < numLEDs) { // Arrays are 0-indexed, thus NOT '<=' |
SomeRandomBloke | 0:582e1b9c1cc1 | 227 | uint8_t *p = &pixels[n * 3]; |
SomeRandomBloke | 0:582e1b9c1cc1 | 228 | // To keep the show() loop as simple & fast as possible, the |
SomeRandomBloke | 0:582e1b9c1cc1 | 229 | // internal color representation is native to different pixel |
SomeRandomBloke | 0:582e1b9c1cc1 | 230 | // types. For compatibility with existing code, 'packed' RGB |
SomeRandomBloke | 0:582e1b9c1cc1 | 231 | // values passed in or out are always 0xRRGGBB order. |
SomeRandomBloke | 0:582e1b9c1cc1 | 232 | if(rgb_order == WS2801_RGB) { |
SomeRandomBloke | 0:582e1b9c1cc1 | 233 | *p++ = c >> 16; // Red |
SomeRandomBloke | 0:582e1b9c1cc1 | 234 | *p++ = c >> 8; // Green |
SomeRandomBloke | 0:582e1b9c1cc1 | 235 | } else { |
SomeRandomBloke | 0:582e1b9c1cc1 | 236 | *p++ = c >> 8; // Green |
SomeRandomBloke | 0:582e1b9c1cc1 | 237 | *p++ = c >> 16; // Red |
SomeRandomBloke | 0:582e1b9c1cc1 | 238 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 239 | *p++ = c; // Blue |
SomeRandomBloke | 0:582e1b9c1cc1 | 240 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 241 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 242 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 243 | // Set pixel color from 'packed' 32-bit RGB value using x,y coordinate system: |
SomeRandomBloke | 3:dfffbd9f8ac6 | 244 | void Adafruit_WS2801::setPixelColor(int16_t x, int16_t y, uint32_t c) |
SomeRandomBloke | 0:582e1b9c1cc1 | 245 | { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 246 | if( x < 0 || x >= width || y < 0 || y >= height ) |
SomeRandomBloke | 3:dfffbd9f8ac6 | 247 | return; // Dont try to update a pixel that doesnt exist |
SomeRandomBloke | 3:dfffbd9f8ac6 | 248 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 249 | bool evenRow = ((y % 2) == 0); |
SomeRandomBloke | 0:582e1b9c1cc1 | 250 | // calculate x offset first |
SomeRandomBloke | 0:582e1b9c1cc1 | 251 | uint16_t offset = x % width; |
SomeRandomBloke | 0:582e1b9c1cc1 | 252 | if (!evenRow) { |
SomeRandomBloke | 0:582e1b9c1cc1 | 253 | offset = (width-1) - offset; |
SomeRandomBloke | 0:582e1b9c1cc1 | 254 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 255 | // add y offset |
SomeRandomBloke | 0:582e1b9c1cc1 | 256 | offset += y * width; |
SomeRandomBloke | 0:582e1b9c1cc1 | 257 | setPixelColor(offset, c); |
SomeRandomBloke | 0:582e1b9c1cc1 | 258 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 259 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 260 | // Query color from previously-set pixel (returns packed 32-bit RGB value) |
SomeRandomBloke | 0:582e1b9c1cc1 | 261 | uint32_t Adafruit_WS2801::getPixelColor(uint16_t n) |
SomeRandomBloke | 0:582e1b9c1cc1 | 262 | { |
SomeRandomBloke | 0:582e1b9c1cc1 | 263 | if(n < numLEDs) { |
SomeRandomBloke | 0:582e1b9c1cc1 | 264 | uint16_t ofs = n * 3; |
SomeRandomBloke | 0:582e1b9c1cc1 | 265 | // To keep the show() loop as simple & fast as possible, the |
SomeRandomBloke | 0:582e1b9c1cc1 | 266 | // internal color representation is native to different pixel |
SomeRandomBloke | 0:582e1b9c1cc1 | 267 | // types. For compatibility with existing code, 'packed' RGB |
SomeRandomBloke | 0:582e1b9c1cc1 | 268 | // values passed in or out are always 0xRRGGBB order. |
SomeRandomBloke | 0:582e1b9c1cc1 | 269 | return (rgb_order == WS2801_RGB) ? |
SomeRandomBloke | 0:582e1b9c1cc1 | 270 | ((uint32_t)pixels[ofs] << 16) | ((uint16_t) pixels[ofs + 1] << 8) | pixels[ofs + 2] : |
SomeRandomBloke | 0:582e1b9c1cc1 | 271 | (pixels[ofs] << 8) | ((uint32_t)pixels[ofs + 1] << 16) | pixels[ofs + 2]; |
SomeRandomBloke | 0:582e1b9c1cc1 | 272 | } |
SomeRandomBloke | 0:582e1b9c1cc1 | 273 | |
SomeRandomBloke | 0:582e1b9c1cc1 | 274 | return 0; // Pixel # is out of bounds |
SomeRandomBloke | 0:582e1b9c1cc1 | 275 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 276 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 277 | // bresenham's algorithm - thx wikpedia |
SomeRandomBloke | 3:dfffbd9f8ac6 | 278 | void Adafruit_WS2801::drawLine(int16_t x0, int16_t y0, |
SomeRandomBloke | 3:dfffbd9f8ac6 | 279 | int16_t x1, int16_t y1, |
SomeRandomBloke | 3:dfffbd9f8ac6 | 280 | uint32_t color) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 281 | int16_t steep = abs(y1 - y0) > abs(x1 - x0); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 282 | if (steep) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 283 | ws_swap(x0, y0); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 284 | ws_swap(x1, y1); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 285 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 286 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 287 | if (x0 > x1) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 288 | ws_swap(x0, x1); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 289 | ws_swap(y0, y1); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 290 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 291 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 292 | int16_t dx, dy; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 293 | dx = x1 - x0; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 294 | dy = abs(y1 - y0); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 295 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 296 | int16_t err = dx / 2; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 297 | int16_t ystep; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 298 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 299 | if (y0 < y1) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 300 | ystep = 1; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 301 | } else { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 302 | ystep = -1; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 303 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 304 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 305 | for (; x0<=x1; x0++) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 306 | if (steep) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 307 | setPixelColor(y0, x0, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 308 | } else { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 309 | setPixelColor(x0, y0, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 310 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 311 | err -= dy; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 312 | if (err < 0) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 313 | y0 += ystep; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 314 | err += dx; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 315 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 316 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 317 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 318 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 319 | void Adafruit_WS2801::drawFastVLine(int16_t x, int16_t y, |
SomeRandomBloke | 3:dfffbd9f8ac6 | 320 | int16_t h, uint32_t color) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 321 | // stupidest version - update in subclasses if desired! |
SomeRandomBloke | 3:dfffbd9f8ac6 | 322 | drawLine(x, y, x, y+h-1, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 323 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 324 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 325 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 326 | void Adafruit_WS2801::drawFastHLine(int16_t x, int16_t y, |
SomeRandomBloke | 3:dfffbd9f8ac6 | 327 | int16_t w, uint32_t color) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 328 | // stupidest version - update in subclasses if desired! |
SomeRandomBloke | 3:dfffbd9f8ac6 | 329 | drawLine(x, y, x+w-1, y, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 330 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 331 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 332 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 333 | // draw a rectangle |
SomeRandomBloke | 3:dfffbd9f8ac6 | 334 | void Adafruit_WS2801::drawRect(int16_t x, int16_t y, |
SomeRandomBloke | 3:dfffbd9f8ac6 | 335 | int16_t w, int16_t h, uint32_t color) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 336 | drawFastHLine(x, y, w, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 337 | drawFastHLine(x, y+h-1, w, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 338 | drawFastVLine(x, y, h, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 339 | drawFastVLine(x+w-1, y, h, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 340 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 341 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 342 | // draw a circle outline |
SomeRandomBloke | 3:dfffbd9f8ac6 | 343 | void Adafruit_WS2801::drawCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 344 | int16_t f = 1 - r; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 345 | int16_t ddF_x = 1; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 346 | int16_t ddF_y = -2 * r; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 347 | int16_t x = 0; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 348 | int16_t y = r; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 349 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 350 | setPixelColor(x0, y0+r, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 351 | setPixelColor(x0, y0-r, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 352 | setPixelColor(x0+r, y0, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 353 | setPixelColor(x0-r, y0, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 354 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 355 | while (x<y) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 356 | if (f >= 0) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 357 | y--; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 358 | ddF_y += 2; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 359 | f += ddF_y; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 360 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 361 | x++; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 362 | ddF_x += 2; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 363 | f += ddF_x; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 364 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 365 | setPixelColor(x0 + x, y0 + y, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 366 | setPixelColor(x0 - x, y0 + y, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 367 | setPixelColor(x0 + x, y0 - y, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 368 | setPixelColor(x0 - x, y0 - y, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 369 | setPixelColor(x0 + y, y0 + x, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 370 | setPixelColor(x0 - y, y0 + x, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 371 | setPixelColor(x0 + y, y0 - x, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 372 | setPixelColor(x0 - y, y0 - x, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 373 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 374 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 375 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 376 | /* |
SomeRandomBloke | 3:dfffbd9f8ac6 | 377 | void Adafruit_WS2801::fillCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 378 | drawFastVLine(x0, y0-r, 2*r+1, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 379 | fillCircleHelper(x0, y0, r, 3, 0, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 380 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 381 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 382 | // used to do circles and roundrects! |
SomeRandomBloke | 3:dfffbd9f8ac6 | 383 | void Adafruit_WS2801::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, |
SomeRandomBloke | 3:dfffbd9f8ac6 | 384 | uint8_t cornername, int16_t delta, uint32_t color) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 385 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 386 | int16_t f = 1 - r; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 387 | int16_t ddF_x = 1; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 388 | int16_t ddF_y = -2 * r; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 389 | int16_t x = 0; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 390 | int16_t y = r; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 391 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 392 | while (x<y) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 393 | if (f >= 0) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 394 | y--; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 395 | ddF_y += 2; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 396 | f += ddF_y; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 397 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 398 | x++; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 399 | ddF_x += 2; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 400 | f += ddF_x; |
SomeRandomBloke | 3:dfffbd9f8ac6 | 401 | |
SomeRandomBloke | 3:dfffbd9f8ac6 | 402 | if (cornername & 0x1) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 403 | drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 404 | drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 405 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 406 | if (cornername & 0x2) { |
SomeRandomBloke | 3:dfffbd9f8ac6 | 407 | drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 408 | drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); |
SomeRandomBloke | 3:dfffbd9f8ac6 | 409 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 410 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 411 | } |
SomeRandomBloke | 3:dfffbd9f8ac6 | 412 | */ |