The port of adafruit dotstar library for arduino https://github.com/adafruit/Adafruit_DotStar

Revision:
1:d09c288b8eb3
Parent:
0:bae97ff743a6
--- a/DotStar.cpp	Fri Mar 25 07:41:51 2016 +0000
+++ b/DotStar.cpp	Wed Apr 06 08:49:21 2016 +0000
@@ -24,35 +24,106 @@
   License along with DotStar.  If not, see <http://www.gnu.org/licenses/>.
   ------------------------------------------------------------------------*/
 
+#include "mbed.h"
 #include "DotStar.h"
-// #include <SPI.h>
-
-SPI spi(p5, p6, p7); // mosi, miso, sclk
 
 // Constructor for hardware SPI -- must connect to MOSI, SCK pins
-Adafruit_DotStar::Adafruit_DotStar(uint16_t n, uint8_t o) :
- numLEDs(n), dataPin(p5), brightness(0), pixels(NULL),
- rOffset(o & 3), gOffset((o >> 2) & 3), bOffset((o >> 4) & 3)
+Adafruit_DotStar::Adafruit_DotStar(uint16_t n, PinName miso, PinName mosi, PinName sclk, int hz, uint8_t o)
+: numLEDs(n)
+, dataPin(USE_HW_SPI)
+, clockPin(USE_HW_SPI)
+, spi(NULL)
+, miso_(miso)
+, mosi_(mosi)
+, sclk_(sclk)
+, data_out(NULL)
+, sclk_out(NULL)
+, port(PortA)
+, port_out(NULL)
+, d_mask(0)
+, c_mask(0)
+, b_use_port(false)
+, brightness(0)
+, pixels(NULL)
+, rOffset(o & 3)
+, gOffset((o >> 2) & 3)
+, bOffset((o >> 4) & 3)
 {
-  updateLength(n);
+    updateLength(n);
 }
 
 // Constructor for 'soft' (bitbang) SPI -- any two pins can be used
-Adafruit_DotStar::Adafruit_DotStar(uint16_t n, uint8_t data, uint8_t clock,
-  uint8_t o) :
- dataPin(data), clockPin(clock), brightness(0), pixels(NULL),
- rOffset(o & 3), gOffset((o >> 2) & 3), bOffset((o >> 4) & 3)
+Adafruit_DotStar::Adafruit_DotStar(uint16_t n, PinName data, PinName clock, uint8_t o)
+: dataPin(data)
+, clockPin(clock)
+, spi(NULL)
+, miso_(NC)
+, mosi_(NC)
+, sclk_(NC)
+, data_out(NULL)
+, sclk_out(NULL)
+, port(PortA)
+, port_out(NULL)
+, d_mask(0)
+, c_mask(0)
+, b_use_port(false)
+, brightness(0)
+, pixels(NULL)
+, rOffset(o & 3)
+, gOffset((o >> 2) & 3)
+, bOffset((o >> 4) & 3)
 {
-  updateLength(n);
+    updateLength(n);
+}
+
+// Constructor for 'soft' (bitbang) SPI -- any two pins can be used
+Adafruit_DotStar::Adafruit_DotStar(uint16_t n, PortName p, int dmask, int cmask, uint8_t o)
+: dataPin(NC)
+, clockPin(NC)
+, spi(NULL)
+, miso_(NC)
+, mosi_(NC)
+, sclk_(NC)
+, data_out(NULL)
+, sclk_out(NULL)
+, port(p)
+, port_out(NULL)
+, d_mask(dmask)
+, c_mask(cmask)
+, b_use_port(true)
+, brightness(0)
+, pixels(NULL)
+, rOffset(o & 3)
+, gOffset((o >> 2) & 3)
+, bOffset((o >> 4) & 3)
+{
+    updateLength(n);
 }
 
 Adafruit_DotStar::~Adafruit_DotStar(void) { // Destructor
-  if(pixels)   free(pixels);
-  hw_spi_end();
+    if(pixels)                free(pixels);
+    if(dataPin == USE_HW_SPI) hw_spi_end();
+    else                      sw_spi_end();
 }
 
 void Adafruit_DotStar::begin(void) { // Initialize SPI
-  hw_spi_init();
+    if(dataPin == USE_HW_SPI) hw_spi_init();
+    else                      sw_spi_init();
+}
+
+// Change to hardware SPI -- must connect to MOSI, SCK pins
+void Adafruit_DotStar::updatePins(void) {
+    sw_spi_end();
+    dataPin = USE_HW_SPI;
+    hw_spi_init();
+}
+
+// Change to 'soft' (bitbang) SPI -- any two pins can be used
+void Adafruit_DotStar::updatePins(PinName data, PinName clock) {
+    hw_spi_end();
+    dataPin  = data;
+    clockPin = clock;
+    sw_spi_init();
 }
 
 // Length can be changed post-constructor for similar reasons (sketch
@@ -60,41 +131,61 @@
 // all that reallocation is likely to fragment and eventually fail.
 // Instead, set length once to longest strip.
 void Adafruit_DotStar::updateLength(uint16_t n) {
-  if(pixels) free(pixels);
-  uint16_t bytes = (rOffset == gOffset) ?
-    n + ((n + 3) / 4) : // MONO: 10 bits/pixel, round up to next byte
-    n * 3;              // COLOR: 3 bytes/pixel
-  if((pixels = (uint8_t *)malloc(bytes))) {
-    numLEDs = n;
-    clear();
-  } else {
-    numLEDs = 0;
-  }
+    if(pixels) free(pixels);
+    uint16_t bytes = (rOffset == gOffset) ?
+        n + ((n + 3) / 4) : // MONO: 10 bits/pixel, round up to next byte
+        n * 3;              // COLOR: 3 bytes/pixel
+    if((pixels = (uint8_t *)malloc(bytes))) {
+        numLEDs = n;
+        clear();
+    } else {
+        numLEDs = 0;
+    }
 }
 
 // SPI STUFF ---------------------------------------------------------------
 
 void Adafruit_DotStar::hw_spi_init(void) { // Initialize hardware SPI
-  // SPI.begin();
-  // SPI.setClockDivider((F_CPU + 4000000L) / 8000000L); // 8-ish MHz on Due
-  // SPI.setBitOrder(MSBFIRST);
-  // SPI.setDataMode(SPI_MODE0);   // Clock Polarity: 0, Clock Phase: 0
-
-  spi.format(8, 0);   // 8bit, mode:0
-  spi.frequency(8000000); // Hz
-
+    spi = new SPI(mosi_, miso_, sclk_); // mosi, miso, sclk
+    spi->format(8, 0);   // 8bit, mode:0
+    spi->frequency(8000000); // Hz
 }
 
 void Adafruit_DotStar::hw_spi_end(void) { // Stop hardware SPI
-  // SPI.end();
+    if (spi) delete spi;
+}
+
+void Adafruit_DotStar::sw_spi_init(void) { // Init 'soft' (bitbang) SPI
+    if (b_use_port) {
+        port_out = new PortOut(port, (d_mask | c_mask));
+    } else {
+        data_out = new DigitalOut(dataPin);
+        sclk_out = new DigitalOut(clockPin);
+    }
 }
 
-
-// All other boards have full-featured hardware support for SPI
+void Adafruit_DotStar::sw_spi_end() { // Stop 'soft' SPI
+    if (port_out) delete(port_out);
+    if (data_out) delete(data_out);
+    if (sclk_out) delete(sclk_out);
+}
 
-//#define spi_out(n) (void)spi.write(n)
-// Pipelining reads next byte while current byte is clocked out
-
+//inline void Adafruit_DotStar::sw_spi_out(uint8_t n) { // Bitbang SPI write
+//    if (b_use_port) {
+//        for(uint8_t i=8; i--; n <<= 1) {
+//            int mask = (n & 0x80) ? (d_mask | c_mask) : c_mask;
+//            *port_out = mask;
+//            *port_out = (mask & ~c_mask);
+//        }
+//    } else {
+//        for(uint8_t i=8; i--; n <<= 1) {
+//            if(n & 0x80) *data_out = 1;
+//            else         *data_out = 0;
+//            *sclk_out = 1;
+//            *sclk_out = 0;
+//        }
+//    }
+//}
 
 /* ISSUE DATA TO LED STRIP -------------------------------------------------
 
@@ -109,76 +200,95 @@
   own use, but any pull requests for this will NOT be merged, nuh uh!
 */
 
-void Adafruit_DotStar::show(void) {
-  if(!pixels) return;
-
-    uint8_t *ptr = pixels;            // -> LED data
-    uint16_t n   = numLEDs;              // Counter
-    uint16_t b16 = (uint16_t)brightness; // Type-convert for fixed-point math
+//inline void Adafruit_DotStar::show() {
+//  if(!pixels) return;
+//
+//    uint8_t *ptr = pixels;            // -> LED data
+//    uint16_t n   = numLEDs;              // Counter
+//    uint16_t b16 = (uint16_t)brightness; // Type-convert for fixed-point math
+//
+//    if(dataPin == USE_HW_SPI) {
+//      
+//      for(size_t i=0; i<4; i++) spi->write(0x00);    // 4 byte start-frame marker
+//      if(brightness) {                     // Scale pixel brightness on output
+//        for (size_t i=n; i>0; i--) {
+//            spi->write(0xFF);                   //  Pixel start
+//            for(size_t j=0; j<3; j++) spi->write((*ptr++ * b16) >> 8); // Scale, write RGB
+//        }
+//      } else {                             // Full brightness (no scaling)
+//        for (size_t i=n; i>0; i--) {
+//            spi->write(0xFF);                   //  Pixel start
+//            for(size_t j=0; j<3; j++) spi->write(*ptr++); // Write R,G,B
+//        }
+//      }
+//      // Four end-frame bytes are seemingly indistinguishable from a white
+//      // pixel, and empirical testing suggests it can be left out...but it's
+//      // always a good idea to follow the datasheet, in case future hardware
+//      // revisions are more strict (e.g. might mandate use of end-frame
+//      // before start-frame marker).  i.e. let's not remove this.
+//      for(size_t i=0; i<4; i++) spi->write(0xFF);
+//
+//  } else {                               // Soft (bitbang) SPI
+//
+//    for(size_t i=0; i<4; i++) sw_spi_out(0);    // Start-frame marker
+//    if(brightness) {                     // Scale pixel brightness on output
+//      do {                               // For each pixel...
+//        sw_spi_out(0xFF);                //  Pixel start
+//        for(size_t i=0; i<3; i++) sw_spi_out((*ptr++ * b16) >> 8); // Scale, write
+//      } while(--n);
+//    } else {                             // Full brightness (no scaling)
+//      do {                               // For each pixel...
+//        sw_spi_out(0xFF);                //  Pixel start
+//        for(size_t i=0; i<3; i++) sw_spi_out(*ptr++); // R,G,B
+//      } while(--n);
+//    }
+//    for(size_t i=0; i<4; i++) sw_spi_out(0xFF); // End-frame marker (see note above)
+//  }
+//}
 
-      for(size_t i=0; i<4; i++) spi.write(0x00);    // 4 byte start-frame marker
-      if(brightness) {                     // Scale pixel brightness on output
-        for (size_t i=n; i>0; i--) {
-            spi.write(0xFF);                   //  Pixel start
-            for(size_t j=0; j<3; j++) spi.write((*ptr++ * b16) >> 8); // Scale, write RGB
-        }
-      } else {                             // Full brightness (no scaling)
-        for (size_t i=n; i>0; i--) {
-            spi.write(0xFF);                   //  Pixel start
-            for(size_t j=0; j<3; j++) spi.write(*ptr++); // Write R,G,B
-        }
-      }
-      // Four end-frame bytes are seemingly indistinguishable from a white
-      // pixel, and empirical testing suggests it can be left out...but it's
-      // always a good idea to follow the datasheet, in case future hardware
-      // revisions are more strict (e.g. might mandate use of end-frame
-      // before start-frame marker).  i.e. let's not remove this.
-      for(size_t i=0; i<4; i++) spi.write(0xFF);
-}
-
-void Adafruit_DotStar::clear() { // Write 0s (off) to full pixel buffer
-  memset(pixels, 0, (rOffset == gOffset) ?
-    numLEDs + ((numLEDs + 3) / 4) : // MONO: 10 bits/pixel
-    numLEDs * 3);                   // COLOR: 3 bytes/pixel
+inline void Adafruit_DotStar::clear() { // Write 0s (off) to full pixel buffer
+    memset(pixels, 0, (rOffset == gOffset) ?
+        numLEDs + ((numLEDs + 3) / 4) : // MONO: 10 bits/pixel
+        numLEDs * 3);                   // COLOR: 3 bytes/pixel
 }
 
 // Set pixel color, separate R,G,B values (0-255 ea.)
-void Adafruit_DotStar::setPixelColor(
- uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
-  if(n < numLEDs) {
-    uint8_t *p = &pixels[n * 3];
-    p[rOffset] = r;
-    p[gOffset] = g;
-    p[bOffset] = b;
-  }
-}
+//inline void Adafruit_DotStar::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
+//{
+//  if(n < numLEDs) {
+//    uint8_t *p = &pixels[n * 3];
+//    p[rOffset] = r;
+//    p[gOffset] = g;
+//    p[bOffset] = b;
+//  }
+//}
 
 // Set pixel color, 'packed' RGB value (0x000000 - 0xFFFFFF)
-void Adafruit_DotStar::setPixelColor(uint16_t n, uint32_t c) {
-  if(n < numLEDs) {
-    uint8_t *p = &pixels[n * 3];
-    p[rOffset] = (uint8_t)(c >> 16);
-    p[gOffset] = (uint8_t)(c >>  8);
-    p[bOffset] = (uint8_t)c;
-  }
+inline void Adafruit_DotStar::setPixelColor(uint16_t n, uint32_t c) {
+    if(n < numLEDs) {
+        uint8_t *p = &pixels[n * 3];
+        p[rOffset] = (uint8_t)(c >> 16);
+        p[gOffset] = (uint8_t)(c >>  8);
+        p[bOffset] = (uint8_t)c;
+    }
 }
 
 // Convert separate R,G,B to packed value
-uint32_t Adafruit_DotStar::Color(uint8_t r, uint8_t g, uint8_t b) {
-  return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
+inline uint32_t Adafruit_DotStar::Color(uint8_t r, uint8_t g, uint8_t b) {
+    return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
 }
 
 // Read color from previously-set pixel, returns packed RGB value.
-uint32_t Adafruit_DotStar::getPixelColor(uint16_t n) const {
-  if(n >= numLEDs) return 0;
-  uint8_t *p = &pixels[n * 3];
-  return ((uint32_t)p[rOffset] << 16) |
-         ((uint32_t)p[gOffset] <<  8) |
-          (uint32_t)p[bOffset];
+inline uint32_t Adafruit_DotStar::getPixelColor(uint16_t n) const {
+    if(n >= numLEDs) return 0;
+    uint8_t *p = &pixels[n * 3];
+    return ((uint32_t)p[rOffset] << 16) |
+           ((uint32_t)p[gOffset] <<  8) |
+            (uint32_t)p[bOffset];
 }
 
-uint16_t Adafruit_DotStar::numPixels(void) { // Ret. strip length
-  return numLEDs;
+inline uint16_t Adafruit_DotStar::numPixels(void) { // Ret. strip length
+    return numLEDs;
 }
 
 // Set global strip brightness.  This does not have an immediate effect;
@@ -188,23 +298,23 @@
 // in this library is 'non destructive' -- it's applied as color data is
 // being issued to the strip, not during setPixel(), and also means that
 // getPixelColor() returns the exact value originally stored.
-void Adafruit_DotStar::setBrightness(uint8_t b) {
-  // Stored brightness value is different than what's passed.  This
-  // optimizes the actual scaling math later, allowing a fast 8x8-bit
-  // multiply and taking the MSB.  'brightness' is a uint8_t, adding 1
-  // here may (intentionally) roll over...so 0 = max brightness (color
-  // values are interpreted literally; no scaling), 1 = min brightness
-  // (off), 255 = just below max brightness.
-  brightness = b + 1;
+inline void Adafruit_DotStar::setBrightness(uint8_t b) {
+    // Stored brightness value is different than what's passed.  This
+    // optimizes the actual scaling math later, allowing a fast 8x8-bit
+    // multiply and taking the MSB.  'brightness' is a uint8_t, adding 1
+    // here may (intentionally) roll over...so 0 = max brightness (color
+    // values are interpreted literally; no scaling), 1 = min brightness
+    // (off), 255 = just below max brightness.
+    brightness = b + 1;
 }
 
-uint8_t Adafruit_DotStar::getBrightness(void) const {
-  return brightness - 1; // Reverse above operation
+inline uint8_t Adafruit_DotStar::getBrightness(void) const {
+    return brightness - 1; // Reverse above operation
 }
 
 // Return pointer to the library's pixel data buffer.  Use carefully,
 // much opportunity for mayhem.  It's mostly for code that needs fast
 // transfers, e.g. SD card to LEDs.  Color data is in BGR order.
-uint8_t *Adafruit_DotStar::getPixels(void) const {
-  return pixels;
+inline uint8_t *Adafruit_DotStar::getPixels(void) const {
+    return pixels;
 }