A conversion of the excellent Adafruit WS2801 library for Arduino to work on mbed
Diff: Adafruit_WS2801.cpp
- Revision:
- 3:dfffbd9f8ac6
- Parent:
- 2:2fdaa13896a4
- Child:
- 4:987c91c45188
--- a/Adafruit_WS2801.cpp Wed Feb 12 22:05:44 2014 +0000 +++ b/Adafruit_WS2801.cpp Tue Jun 03 15:45:14 2014 +0000 @@ -1,6 +1,7 @@ #include "mbed.h" #include "Adafruit_WS2801.h" + // Example to control WS2801-based RGB LED Modules in a strand or strip // Written by Adafruit - MIT license /*****************************************************************************/ @@ -8,19 +9,22 @@ SPI spi(p16, p15, p13); // mosi, miso, sclk // Constructor for use with hardware SPI (specific clock/data pins): -//Adafruit_WS2801::Adafruit_WS2801(uint16_t n, uint8_t order): clkpin(PTD4), datapin(PTA12) -//{ -// rgb_order = order; -// alloc(n); -// updatePins(); -//} - -// Constructor for use with arbitrary clock/data pins: -Adafruit_WS2801::Adafruit_WS2801(uint16_t n, PinName dpin, PinName cpin, uint8_t order) : clkpin(cpin), datapin(dpin) +/*Adafruit_WS2801::Adafruit_WS2801(uint16_t n, uint8_t order): clkpin(PTD4), datapin(PTA12) { rgb_order = order; alloc(n); - + updatePins(); +}*/ + +// Constructor for use with arbitrary clock/data pins: +Adafruit_WS2801::Adafruit_WS2801(int16_t n, PinName dpin, PinName cpin, uint8_t order) + : clkpin(cpin), datapin(dpin) +{ + rgb_order = order; + alloc(n); + width = 1; + height = n; + hardwareSPI = false; // updatePins(dpin, cpin); } @@ -28,12 +32,14 @@ // assumes configuration where string starts at coordinate 0,0 and continues to w-1,0, w-1,1 // and on to 0,1, 0,2 and on to w-1,2 and so on. Snaking back and forth till the end. // other function calls with provide access to pixels via an x,y coordinate system -Adafruit_WS2801::Adafruit_WS2801(uint16_t w, uint16_t h, PinName dpin, PinName cpin, uint8_t order) : clkpin(cpin), datapin(dpin) +Adafruit_WS2801::Adafruit_WS2801(int16_t w, int16_t h, PinName dpin, PinName cpin, uint8_t order) + : clkpin(cpin), datapin(dpin) { rgb_order = order; alloc(w * h); width = w; height = h; + hardwareSPI = false; // updatePins(dpin, cpin); } @@ -42,7 +48,7 @@ { begun = false; numLEDs = ((pixels = (uint8_t *)calloc(n, 3)) != NULL) ? n : 0; - + hardwareSPI = true; // for(int bits = 0; bits <= numLEDs*24; bits++) { // spi.write(0x00); @@ -53,6 +59,23 @@ // clkpin = 0; } +// Constructor for use with a matrix configuration, specify w, h for size of matrix +// assumes configuration where string starts at coordinate 0,0 and continues to w-1,0, w-1,1 +// and on to 0,1, 0,2 and on to w-1,2 and so on. Snaking back and forth till the end. +// other function calls with provide access to pixels via an x,y coordinate system +/*Adafruit_WS2801::Adafruit_WS2801(uint16_t w, uint16_t h, uint8_t order) +{ + rgb_order = order; + alloc(w * h); + width = w; + height = h; + hardwareSPI = true; +// updatePins(dpin, cpin); +} +*/ + + + // via Michael Vogt/neophob: empty constructor is used when strand length // isn't known at compile-time; situations where program config might be // read from internal flash memory or an SD card, or arrive via serial @@ -101,15 +124,16 @@ // Change pin assignments post-constructor, using arbitrary pins: -//void Adafruit_WS2801::updatePins(PinName dpin, PinName cpin) -//{ +void Adafruit_WS2801::updatePins(PinName dpin, PinName cpin) +{ // Note: any prior clock/data pin directions are left as-is and are // NOT restored as inputs! -// datapin = DigitalOut(dpin); -// clkpin = DigitalOut(cpin); -//} + datapin = DigitalOut(dpin); + clkpin = DigitalOut(cpin); +} +// Return the number of LEDs uint16_t Adafruit_WS2801::numPixels(void) { return numLEDs; @@ -140,7 +164,7 @@ for(i=0; i<nl3; i++ ) { spi.write( pixels[i]); } - wait_ms(1); // Data is latched by holding clock pin low for 1 millisecond + // wait_ms(1); // Needed???? } else { uint8_t bit; @@ -179,11 +203,15 @@ } // Set pixel color from separate 8-bit R, G, B components using x,y coordinate system: -void Adafruit_WS2801::setPixelColor(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b) +void Adafruit_WS2801::setPixelColor(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b) { + if( x < 0 || x >= width || y < 0 || y >= height ) + return; // Dont try to update a pixel that doesnt exist + bool evenRow = ((y % 2) == 0); // calculate x offset first uint16_t offset = x % width; + if (!evenRow) { offset = (width-1) - offset; } @@ -195,7 +223,7 @@ // Set pixel color from 'packed' 32-bit RGB value: void Adafruit_WS2801::setPixelColor(uint16_t n, uint32_t c) { - if(n < numLEDs) { // Arrays are 0-indexed, thus NOT '<=' + if( n < numLEDs) { // Arrays are 0-indexed, thus NOT '<=' uint8_t *p = &pixels[n * 3]; // To keep the show() loop as simple & fast as possible, the // internal color representation is native to different pixel @@ -213,8 +241,11 @@ } // Set pixel color from 'packed' 32-bit RGB value using x,y coordinate system: -void Adafruit_WS2801::setPixelColor(uint16_t x, uint16_t y, uint32_t c) +void Adafruit_WS2801::setPixelColor(int16_t x, int16_t y, uint32_t c) { + if( x < 0 || x >= width || y < 0 || y >= height ) + return; // Dont try to update a pixel that doesnt exist + bool evenRow = ((y % 2) == 0); // calculate x offset first uint16_t offset = x % width; @@ -242,3 +273,140 @@ return 0; // Pixel # is out of bounds } + +// bresenham's algorithm - thx wikpedia +void Adafruit_WS2801::drawLine(int16_t x0, int16_t y0, + int16_t x1, int16_t y1, + uint32_t color) { + int16_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + ws_swap(x0, y0); + ws_swap(x1, y1); + } + + if (x0 > x1) { + ws_swap(x0, x1); + ws_swap(y0, y1); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + for (; x0<=x1; x0++) { + if (steep) { + setPixelColor(y0, x0, color); + } else { + setPixelColor(x0, y0, color); + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } + } +} + +void Adafruit_WS2801::drawFastVLine(int16_t x, int16_t y, + int16_t h, uint32_t color) { + // stupidest version - update in subclasses if desired! + drawLine(x, y, x, y+h-1, color); +} + + +void Adafruit_WS2801::drawFastHLine(int16_t x, int16_t y, + int16_t w, uint32_t color) { + // stupidest version - update in subclasses if desired! + drawLine(x, y, x+w-1, y, color); +} + + +// draw a rectangle +void Adafruit_WS2801::drawRect(int16_t x, int16_t y, + int16_t w, int16_t h, uint32_t color) { + drawFastHLine(x, y, w, color); + drawFastHLine(x, y+h-1, w, color); + drawFastVLine(x, y, h, color); + drawFastVLine(x+w-1, y, h, color); +} + +// draw a circle outline +void Adafruit_WS2801::drawCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color) { + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + setPixelColor(x0, y0+r, color); + setPixelColor(x0, y0-r, color); + setPixelColor(x0+r, y0, color); + setPixelColor(x0-r, y0, color); + + while (x<y) { + if (f >= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + setPixelColor(x0 + x, y0 + y, color); + setPixelColor(x0 - x, y0 + y, color); + setPixelColor(x0 + x, y0 - y, color); + setPixelColor(x0 - x, y0 - y, color); + setPixelColor(x0 + y, y0 + x, color); + setPixelColor(x0 - y, y0 + x, color); + setPixelColor(x0 + y, y0 - x, color); + setPixelColor(x0 - y, y0 - x, color); + + } +} +/* +void Adafruit_WS2801::fillCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color) { + drawFastVLine(x0, y0-r, 2*r+1, color); + fillCircleHelper(x0, y0, r, 3, 0, color); +} + +// used to do circles and roundrects! +void Adafruit_WS2801::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, + uint8_t cornername, int16_t delta, uint32_t color) { + + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + while (x<y) { + if (f >= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) { + drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); + } + if (cornername & 0x2) { + drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); + } + } +} +*/