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

DotStar.h

Committer:
hideakitai
Date:
2016-04-06
Revision:
1:d09c288b8eb3
Parent:
0:bae97ff743a6

File content as of revision 1:d09c288b8eb3:

/*------------------------------------------------------------------------
  This file is part of the Adafruit Dot Star library.

  Adafruit Dot Star is free software: you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public License
  as published by the Free Software Foundation, either version 3 of
  the License, or (at your option) any later version.

  Adafruit Dot Star is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with DotStar.  If not, see <http://www.gnu.org/licenses/>.
  ------------------------------------------------------------------------*/

#ifndef _ADAFRUIT_DOT_STAR_H_
#define _ADAFRUIT_DOT_STAR_H_

#include <mbed.h>

// Color-order flag for LED pixels (optional extra parameter to constructor):
// Bits 0,1 = R index (0-2), bits 2,3 = G index, bits 4,5 = B index
#define DOTSTAR_RGB (0 | (1 << 2) | (2 << 4))
#define DOTSTAR_RBG (0 | (2 << 2) | (1 << 4))
#define DOTSTAR_GRB (1 | (0 << 2) | (2 << 4))
#define DOTSTAR_GBR (2 | (0 << 2) | (1 << 4))
#define DOTSTAR_BRG (1 | (2 << 2) | (0 << 4))
#define DOTSTAR_BGR (2 | (1 << 2) | (0 << 4))
#define DOTSTAR_MONO 0 // Single-color strip WIP DO NOT USE YET

#define USE_HW_SPI NC // Assign this to dataPin to indicate 'hard' SPI


class Adafruit_DotStar {

public:

    Adafruit_DotStar(uint16_t n, PinName miso, PinName mosi, PinName sclk, int hz = 8000000, uint8_t o=DOTSTAR_BRG);
    Adafruit_DotStar(uint16_t n, PinName d, PinName c, uint8_t o=DOTSTAR_BRG);
    Adafruit_DotStar(uint16_t n, PortName p, int d_mask, int c_mask, uint8_t o=DOTSTAR_BRG);
    ~Adafruit_DotStar(void);
   
    void begin(void);                            // Prime pins/SPI for output
    void clear();                                // Set all pixel data to zero
    void setBrightness(uint8_t);                 // Set global brightness 0-255
    void setPixelColor(uint16_t n, uint32_t c);
    void 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;
        }
    }
    void show(void)                             // Issue color data to strip
    {
        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)
        }
    }
    void updatePins(void);                       // Change pin assignments (HW)
    void updatePins(PinName d, PinName c);       // Change pin assignments (SW)
    void updateLength(uint16_t n);               // Change length
    uint32_t Color(uint8_t r, uint8_t g, uint8_t b); // R,G,B to 32-bit color
    uint32_t getPixelColor(uint16_t n) const;        // Return 32-bit pixel color
    uint16_t numPixels(void);                        // Return number of pixels
    uint8_t  getBrightness(void) const;              // Return global brightness
    uint8_t* getPixels(void) const;                  // Return pixel data pointer

 private:

    uint16_t numLEDs;                                // Number of pixels
    PinName dataPin;                                // If soft SPI, data pin #
    PinName clockPin;                               // If soft SPI, clock pin #
    SPI* spi;
    PinName miso_;
    PinName mosi_;
    PinName sclk_;
    DigitalOut* data_out;
    DigitalOut* sclk_out;
    PortName port;
    PortOut* port_out;
    int d_mask;
    int c_mask;
    bool b_use_port;
    uint8_t brightness;                             // Global brightness setting
    uint8_t* pixels;                                 // LED RGB values (3 bytes ea.)
    uint8_t rOffset;                                // Index of red in 3-byte pixel
    uint8_t gOffset;                                // Index of green byte
    uint8_t bOffset;                                // Index of blue byte
    
    void hw_spi_init(void);                      // Start hardware SPI
    void hw_spi_end(void);                       // Stop hardware SPI
    void sw_spi_init(void);                      // Start bitbang SPI
    void sw_spi_end(void);                       // Stop bitbang SPI
    inline void 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;
            }
        }
    }
    
};

#endif // _ADAFRUIT_DOT_STAR_H_