Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DotStar by
DotStar.cpp
00001 /*------------------------------------------------------------------------ 00002 Arduino library to control Adafruit Dot Star addressable RGB LEDs. 00003 00004 Written by Limor Fried and Phil Burgess for Adafruit Industries. 00005 00006 Adafruit invests time and resources providing this open source code, 00007 please support Adafruit and open-source hardware by purchasing products 00008 from Adafruit! 00009 00010 ------------------------------------------------------------------------ 00011 This file is part of the Adafruit Dot Star library. 00012 00013 Adafruit Dot Star is free software: you can redistribute it and/or 00014 modify it under the terms of the GNU Lesser General Public License 00015 as published by the Free Software Foundation, either version 3 of 00016 the License, or (at your option) any later version. 00017 00018 Adafruit Dot Star is distributed in the hope that it will be useful, 00019 but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00021 GNU Lesser General Public License for more details. 00022 00023 You should have received a copy of the GNU Lesser General Public 00024 License along with DotStar. If not, see <http://www.gnu.org/licenses/>. 00025 ------------------------------------------------------------------------*/ 00026 00027 #include "mbed.h" 00028 #include "DotStar.h" 00029 00030 // Constructor for hardware SPI -- must connect to MOSI, SCK pins 00031 Adafruit_DotStar::Adafruit_DotStar(uint16_t n, PinName miso, PinName mosi, PinName sclk, int hz, uint8_t o) 00032 : numLEDs(n) 00033 , dataPin(USE_HW_SPI) 00034 , clockPin(USE_HW_SPI) 00035 , spi(NULL) 00036 , miso_(miso) 00037 , mosi_(mosi) 00038 , sclk_(sclk) 00039 , data_out(NULL) 00040 , sclk_out(NULL) 00041 , port(Port0) 00042 , port_out(NULL) 00043 , d_mask(0) 00044 , c_mask(0) 00045 , b_use_port(false) 00046 , brightness(0) 00047 , pixels(NULL) 00048 , rOffset(o & 3) 00049 , gOffset((o >> 2) & 3) 00050 , bOffset((o >> 4) & 3) 00051 { 00052 updateLength(n); 00053 } 00054 00055 // Constructor for 'soft' (bitbang) SPI -- any two pins can be used 00056 Adafruit_DotStar::Adafruit_DotStar(uint16_t n, PinName data, PinName clock, uint8_t o) 00057 : dataPin(data) 00058 , clockPin(clock) 00059 , spi(NULL) 00060 , miso_(NC) 00061 , mosi_(NC) 00062 , sclk_(NC) 00063 , data_out(NULL) 00064 , sclk_out(NULL) 00065 , port(Port0) 00066 , port_out(NULL) 00067 , d_mask(0) 00068 , c_mask(0) 00069 , b_use_port(false) 00070 , brightness(0) 00071 , pixels(NULL) 00072 , rOffset(o & 3) 00073 , gOffset((o >> 2) & 3) 00074 , bOffset((o >> 4) & 3) 00075 { 00076 updateLength(n); 00077 } 00078 00079 // Constructor for 'soft' (bitbang) SPI -- any two pins can be used 00080 Adafruit_DotStar::Adafruit_DotStar(uint16_t n, PortName p, int dmask, int cmask, uint8_t o) 00081 : dataPin(NC) 00082 , clockPin(NC) 00083 , spi(NULL) 00084 , miso_(NC) 00085 , mosi_(NC) 00086 , sclk_(NC) 00087 , data_out(NULL) 00088 , sclk_out(NULL) 00089 , port(p) 00090 , port_out(NULL) 00091 , d_mask(dmask) 00092 , c_mask(cmask) 00093 , b_use_port(true) 00094 , brightness(0) 00095 , pixels(NULL) 00096 , rOffset(o & 3) 00097 , gOffset((o >> 2) & 3) 00098 , bOffset((o >> 4) & 3) 00099 { 00100 updateLength(n); 00101 } 00102 00103 Adafruit_DotStar::~Adafruit_DotStar(void) { // Destructor 00104 if(pixels) free(pixels); 00105 if(dataPin == USE_HW_SPI) hw_spi_end(); 00106 else sw_spi_end(); 00107 } 00108 00109 void Adafruit_DotStar::begin(void) { // Initialize SPI 00110 if(dataPin == USE_HW_SPI) hw_spi_init(); 00111 else sw_spi_init(); 00112 } 00113 00114 // Change to hardware SPI -- must connect to MOSI, SCK pins 00115 void Adafruit_DotStar::updatePins(void) { 00116 sw_spi_end(); 00117 dataPin = USE_HW_SPI; 00118 hw_spi_init(); 00119 } 00120 00121 // Change to 'soft' (bitbang) SPI -- any two pins can be used 00122 void Adafruit_DotStar::updatePins(PinName data, PinName clock) { 00123 hw_spi_end(); 00124 dataPin = data; 00125 clockPin = clock; 00126 sw_spi_init(); 00127 } 00128 00129 // Length can be changed post-constructor for similar reasons (sketch 00130 // config not hardcoded). But DON'T use this for "recycling" strip RAM... 00131 // all that reallocation is likely to fragment and eventually fail. 00132 // Instead, set length once to longest strip. 00133 void Adafruit_DotStar::updateLength(uint16_t n) { 00134 if(pixels) free(pixels); 00135 uint16_t bytes = (rOffset == gOffset) ? 00136 n + ((n + 3) / 4) : // MONO: 10 bits/pixel, round up to next byte 00137 n * 3; // COLOR: 3 bytes/pixel 00138 if((pixels = (uint8_t *)malloc(bytes))) { 00139 numLEDs = n; 00140 clear(); 00141 } else { 00142 numLEDs = 0; 00143 } 00144 } 00145 00146 // SPI STUFF --------------------------------------------------------------- 00147 00148 void Adafruit_DotStar::hw_spi_init(void) { // Initialize hardware SPI 00149 spi = new SPI(mosi_, miso_, sclk_); // mosi, miso, sclk 00150 spi->format(8, 0); // 8bit, mode:0 00151 spi->frequency(8000000); // Hz 00152 } 00153 00154 void Adafruit_DotStar::hw_spi_end(void) { // Stop hardware SPI 00155 if (spi) delete spi; 00156 } 00157 00158 void Adafruit_DotStar::sw_spi_init(void) { // Init 'soft' (bitbang) SPI 00159 if (b_use_port) { 00160 port_out = new PortOut(port, (d_mask | c_mask)); 00161 } else { 00162 data_out = new DigitalOut(dataPin); 00163 sclk_out = new DigitalOut(clockPin); 00164 } 00165 } 00166 00167 void Adafruit_DotStar::sw_spi_end() { // Stop 'soft' SPI 00168 if (port_out) delete(port_out); 00169 if (data_out) delete(data_out); 00170 if (sclk_out) delete(sclk_out); 00171 } 00172 00173 //inline void Adafruit_DotStar::sw_spi_out(uint8_t n) { // Bitbang SPI write 00174 // if (b_use_port) { 00175 // for(uint8_t i=8; i--; n <<= 1) { 00176 // int mask = (n & 0x80) ? (d_mask | c_mask) : c_mask; 00177 // *port_out = mask; 00178 // *port_out = (mask & ~c_mask); 00179 // } 00180 // } else { 00181 // for(uint8_t i=8; i--; n <<= 1) { 00182 // if(n & 0x80) *data_out = 1; 00183 // else *data_out = 0; 00184 // *sclk_out = 1; 00185 // *sclk_out = 0; 00186 // } 00187 // } 00188 //} 00189 00190 /* ISSUE DATA TO LED STRIP ------------------------------------------------- 00191 00192 Although the LED driver has an additional per-pixel 5-bit brightness 00193 setting, it is NOT used or supported here because it's a brain-dead 00194 misfeature that's counter to the whole point of Dot Stars, which is to 00195 have a much faster PWM rate than NeoPixels. It gates the high-speed 00196 PWM output through a second, much slower PWM (about 400 Hz), rendering 00197 it useless for POV. This brings NOTHING to the table that can't be 00198 already handled better in one's sketch code. If you really can't live 00199 without this abomination, you can fork the library and add it for your 00200 own use, but any pull requests for this will NOT be merged, nuh uh! 00201 */ 00202 00203 //inline void Adafruit_DotStar::show() { 00204 // if(!pixels) return; 00205 // 00206 // uint8_t *ptr = pixels; // -> LED data 00207 // uint16_t n = numLEDs; // Counter 00208 // uint16_t b16 = (uint16_t)brightness; // Type-convert for fixed-point math 00209 // 00210 // if(dataPin == USE_HW_SPI) { 00211 // 00212 // for(size_t i=0; i<4; i++) spi->write(0x00); // 4 byte start-frame marker 00213 // if(brightness) { // Scale pixel brightness on output 00214 // for (size_t i=n; i>0; i--) { 00215 // spi->write(0xFF); // Pixel start 00216 // for(size_t j=0; j<3; j++) spi->write((*ptr++ * b16) >> 8); // Scale, write RGB 00217 // } 00218 // } else { // Full brightness (no scaling) 00219 // for (size_t i=n; i>0; i--) { 00220 // spi->write(0xFF); // Pixel start 00221 // for(size_t j=0; j<3; j++) spi->write(*ptr++); // Write R,G,B 00222 // } 00223 // } 00224 // // Four end-frame bytes are seemingly indistinguishable from a white 00225 // // pixel, and empirical testing suggests it can be left out...but it's 00226 // // always a good idea to follow the datasheet, in case future hardware 00227 // // revisions are more strict (e.g. might mandate use of end-frame 00228 // // before start-frame marker). i.e. let's not remove this. 00229 // for(size_t i=0; i<4; i++) spi->write(0xFF); 00230 // 00231 // } else { // Soft (bitbang) SPI 00232 // 00233 // for(size_t i=0; i<4; i++) sw_spi_out(0); // Start-frame marker 00234 // if(brightness) { // Scale pixel brightness on output 00235 // do { // For each pixel... 00236 // sw_spi_out(0xFF); // Pixel start 00237 // for(size_t i=0; i<3; i++) sw_spi_out((*ptr++ * b16) >> 8); // Scale, write 00238 // } while(--n); 00239 // } else { // Full brightness (no scaling) 00240 // do { // For each pixel... 00241 // sw_spi_out(0xFF); // Pixel start 00242 // for(size_t i=0; i<3; i++) sw_spi_out(*ptr++); // R,G,B 00243 // } while(--n); 00244 // } 00245 // for(size_t i=0; i<4; i++) sw_spi_out(0xFF); // End-frame marker (see note above) 00246 // } 00247 //} 00248 00249 inline void Adafruit_DotStar::clear() { // Write 0s (off) to full pixel buffer 00250 memset(pixels, 0, (rOffset == gOffset) ? 00251 numLEDs + ((numLEDs + 3) / 4) : // MONO: 10 bits/pixel 00252 numLEDs * 3); // COLOR: 3 bytes/pixel 00253 } 00254 00255 // Set pixel color, separate R,G,B values (0-255 ea.) 00256 //inline void Adafruit_DotStar::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) 00257 //{ 00258 // if(n < numLEDs) { 00259 // uint8_t *p = &pixels[n * 3]; 00260 // p[rOffset] = r; 00261 // p[gOffset] = g; 00262 // p[bOffset] = b; 00263 // } 00264 //} 00265 00266 // Set pixel color, 'packed' RGB value (0x000000 - 0xFFFFFF) 00267 inline void Adafruit_DotStar::setPixelColor(uint16_t n, uint32_t c) { 00268 if(n < numLEDs) { 00269 uint8_t *p = &pixels[n * 3]; 00270 p[rOffset] = (uint8_t)(c >> 16); 00271 p[gOffset] = (uint8_t)(c >> 8); 00272 p[bOffset] = (uint8_t)c; 00273 } 00274 } 00275 00276 // Convert separate R,G,B to packed value 00277 inline uint32_t Adafruit_DotStar::Color(uint8_t r, uint8_t g, uint8_t b) { 00278 return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; 00279 } 00280 00281 // Read color from previously-set pixel, returns packed RGB value. 00282 inline uint32_t Adafruit_DotStar::getPixelColor(uint16_t n) const { 00283 if(n >= numLEDs) return 0; 00284 uint8_t *p = &pixels[n * 3]; 00285 return ((uint32_t)p[rOffset] << 16) | 00286 ((uint32_t)p[gOffset] << 8) | 00287 (uint32_t)p[bOffset]; 00288 } 00289 00290 inline uint16_t Adafruit_DotStar::numPixels(void) { // Ret. strip length 00291 return numLEDs; 00292 } 00293 00294 // Set global strip brightness. This does not have an immediate effect; 00295 // must be followed by a call to show(). Not a fan of this...for various 00296 // reasons I think it's better handled in one's sketch, but it's here for 00297 // parity with the NeoPixel library. Good news is that brightness setting 00298 // in this library is 'non destructive' -- it's applied as color data is 00299 // being issued to the strip, not during setPixel(), and also means that 00300 // getPixelColor() returns the exact value originally stored. 00301 inline void Adafruit_DotStar::setBrightness(uint8_t b) { 00302 // Stored brightness value is different than what's passed. This 00303 // optimizes the actual scaling math later, allowing a fast 8x8-bit 00304 // multiply and taking the MSB. 'brightness' is a uint8_t, adding 1 00305 // here may (intentionally) roll over...so 0 = max brightness (color 00306 // values are interpreted literally; no scaling), 1 = min brightness 00307 // (off), 255 = just below max brightness. 00308 brightness = b + 1; 00309 } 00310 00311 inline uint8_t Adafruit_DotStar::getBrightness(void) const { 00312 return brightness - 1; // Reverse above operation 00313 } 00314 00315 // Return pointer to the library's pixel data buffer. Use carefully, 00316 // much opportunity for mayhem. It's mostly for code that needs fast 00317 // transfers, e.g. SD card to LEDs. Color data is in BGR order. 00318 inline uint8_t *Adafruit_DotStar::getPixels(void) const { 00319 return pixels; 00320 }
Generated on Wed Jul 13 2022 23:09:12 by
