diff --git a/ObjectFLED.h b/ObjectFLED.h index cf5e6bf..6c2bdc7 100644 --- a/ObjectFLED.h +++ b/ObjectFLED.h @@ -58,9 +58,9 @@ #define CORDER_RGB 0 //* WS2811, YF923 #define CORDER_RBG 1 #define CORDER_GRB 2 //* WS2811B, Most LED strips are wired this way -#define CORDER_GBR 3 +#define CORDER_GBR 3 //* #define CORDER_BRG 4 //* Adafruit Product ID: 5984 As of November 5, 2024 - this strand has different 'internal' color ordering. It's now BRG not RGB, -#define CORDER_BGR 5 // Adafruit Dotstar LEDs SK9822 uses this CO but they use inverted start/stop bits +#define CORDER_BGR 5 //* Adafruit Dotstar LEDs SK9822 uses this CO but they use inverted start/stop bits #define CORDER_RGBW 6 //* Popular #define CORDER_RBGW 7 #define CORDER_GRBW 8 diff --git a/OjectFLED.cpp b/OjectFLED.cpp index 1954013..799b796 100644 --- a/OjectFLED.cpp +++ b/OjectFLED.cpp @@ -52,6 +52,7 @@ GOIO9List = { 2, 3, 4, 5, 29, 33, 48, 49, 50, 51, 52, 53, 54 } //6 top, 7 botto * Added setBrightness(), setBalance() * FrameBuffer no longer passed in, constructor now creates buffer; destructor added * Added support for per-object setting of OC factor, TH+TL, T0H, T1H, and LATCH_DELAY in begin function +* Set DSE=3, SPEED=0, SRE=0 on output pins per experiment & PJRC forum guidance */ #ifndef __IMXRT1062__ @@ -303,6 +304,22 @@ void ObjectFLED::genFrameBuffer(uint32_t serp) { j += 3; } //for(leds in drawbuffer) break; + case CORDER_GBR: + for (uint16_t i = 0; i < (numbytes * numpins); i += 3) { + *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025; + *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025; + *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025; + j += 3; + } //for(leds in drawbuffer) + break; + case CORDER_BGR: + for (uint16_t i = 0; i < (numbytes * numpins); i += 3) { + *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025; + *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025; + *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025; + j += 3; + } //for(leds in drawbuffer) + break; case CORDER_BRG: for (uint16_t i = 0; i < (numbytes * numpins); i += 3) { *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j) * rLevel / 65025; @@ -346,6 +363,30 @@ void ObjectFLED::genFrameBuffer(uint32_t serp) { j += jChange; } //for(leds in drawbuffer) break; + case CORDER_GBR: + for (uint16_t i = 0; i < (numbytes * numpins); i += 3) { + if (i % (serp * 3) == 0) { + if (jChange < 0) { j = i; jChange = 3; } + else { j = i + (serp - 1) * 3; jChange = -3; } + } + *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025; + *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025; + *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025; + j += 3; + } //for(leds in drawbuffer) + break; + case CORDER_BGR: + for (uint16_t i = 0; i < (numbytes * numpins); i += 3) { + if (i % (serp * 3) == 0) { + if (jChange < 0) { j = i; jChange = 3; } + else { j = i + (serp - 1) * 3; jChange = -3; } + } + *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025; + *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025; + *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025; + j += 3; + } //for(leds in drawbuffer) + break; case CORDER_BRG: for (uint16_t i = 0; i < (numbytes * numpins); i += 3) { if (i % (serp * 3) == 0) { @@ -541,17 +582,17 @@ int ObjectFLED::busy(void) void ObjectFLED::setBrightness(uint8_t brightLevel) { brightness = brightLevel; - rLevel = (brightness + 1) * (colorBalance >> 16); - gLevel = (brightness + 1) * ((colorBalance >> 8) & 0xFF); - bLevel = (brightness + 1) * (colorBalance & 0xFF); + rLevel = brightness * (colorBalance >> 16); + gLevel = brightness * ((colorBalance >> 8) & 0xFF); + bLevel = brightness * (colorBalance & 0xFF); } void ObjectFLED::setBalance(uint32_t balMask) { colorBalance = balMask & 0xFFFFFF; - rLevel = (brightness + 1) * (colorBalance >> 16); - gLevel = (brightness + 1) * ((colorBalance >> 8) & 0xFF); - bLevel = (brightness + 1) * (colorBalance & 0xFF); + rLevel = brightness * (colorBalance >> 16); + gLevel = brightness * ((colorBalance >> 8) & 0xFF); + bLevel = brightness * (colorBalance & 0xFF); } diff --git a/README.md b/README.md index d9de555..f45dc65 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ # ObjectFLED.h -Allows for configuration and control of multiple (physical) digital LED display objects +FastLED-friendly LED display driver allows for configuration and control of multiple digital LED display devices independently in code. Display objects use DMA transfer (from [OctoWS2811 library](http://www.pjrc.com/teensy/td_libs_OctoWS2811.html)) -on any or all 40 or 55 pins of Teensy 4.0 or 4.1 to drive digital LEDs with massive parallelism, -if needed. +on any or all 40 or 55 pins of Teensy 4.0 or 4.1 to drive digital LEDs with massive parallelism. The show() function is non-blocking, returning control to the graphics drawing code in just 6% of the time it takes to complete buffer transmission to an LED string (tested with WS2812B, 1.6 @@ -22,7 +21,7 @@ planes of a cube, a single string of house lights, an orbit of an electron, etc. - For Teensy 4.x only. It may be possible to add other boards if they support DMA driven by configurable timers, and ability to map digital pins to a data register which DMA can target. - - LED data color formats: RGB, GRB, BRG, and RGBW + - LED data color formats: RGB, GRB, BRG, GBR, BGR and RGBW ## MAIN BENEFITS @@ -30,7 +29,7 @@ planes of a cube, a single string of house lights, an orbit of an electron, etc. * You can independently configure, control and display multiple LED devices connected to your Teensy 4.x, even if the devices use different LED types with different specs. Combine LED devices into a single display object, or define separate objects for segments of each device, or just plain -one display object for each device (segmentation is automatic). It is also possible to define 2 +one display object for each device. It is also possible to define 2 display objects to display the same drawing buffer on 2 different LED devices. * Large LED devices can be driven with parallel output to separate segments of the device. Physical @@ -45,21 +44,12 @@ bytes per LED in RGB order. * You can tweak the shape of the LED data waveform generated by this driver. By calling begin() with full pulse timing specs, you can tweak the waveform to achieve the highest possible overclock -(and highest back-to-back refresh rate). Each display object has it's own begin() function, and -it's own LED timing. - -* The show() function is non-blocking, and returns in just 6% of the time required to write a single -segment. However when calling show() back-to-back, each must wait for the prior to complete it's -latch pulse at the end of writing. This is also true when calling show() for one object right after -calling show() for another object. All display objects share the same DMA-Timer pipeline in hardware. -Therefore, for code which controls a large LED device and a small one, with sequential calls to each -show(): show the small one first, then show the large one, then update your drawing while the large -display is still DMA-transmitting 94% of it's LED data. +(and highest back-to-back refresh rate). * Show() function has built-in handling for serpentine, color order, brightness, and color balance for each object. Like in FastLED, these are applied to the frame buffer, not your drawing buffer. Get and set functions for brightness and colormask are included (the ones in FastLED won't work on -ObjectFLED display objects). +ObjectFLED display objects). These are applied independently to each display object in your sketch. * Accessory functions included to fade a drawing array to a color other than black, and to draw a square on an LED plane. @@ -78,7 +68,8 @@ level). When taking advantage of parallel inputs into an LED device, each pin is assumed to drive the same number of LEDs (or rows or planes). When you define your ObjectFLED object, provide an ordered pin -list which matches the order in which the pins connect to the device. ObjectFLED will output segments from your display buffer to those pins in the order you specify. +list which matches the order in which the pins connect to the device. ObjectFLED will output +segments from your display buffer to those pins in the order you specify, and simultaneously. Individual LEDs come with various formats for RGB color order, data signal clock frequency, and pulse timing specs. ObjectFLED defaults will work for popular RGB-order LEDs with 800KHz clock and @@ -152,7 +143,12 @@ NOTE: In test I had to use 72uS latch delay for LEDs with a spec of 50uS, in ord ### show() FUNCTION -See MAIN BENEFITS above for details. +See MAIN BENEFITS above for details. When calling show() back-to-back, each must wait for the prior to complete it's +latch pulse at the end of writing. This is also true when calling show() for one object right after +calling show() for another object. All display objects share the same DMA-Timer pipeline in hardware. +Therefore, for code which controls a large LED device and a small one, with sequential calls to each +show(): show the small one first, then show the large one, then update your drawing while the large +display is still DMA-transmitting 94% of it's LED data. **Example:** diff --git a/library.properties b/library.properties index 3922b9f..7dfa85d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ObjectFLED -version=1.0.2 +version=1.0.3 author=Kurt Funderburg maintainer=Kurt Funderburg sentence=Independently configure and display to various LED devices in one sketch with parallel DMA-driven LED output.