FastLED 3.10.6
Loading...
Searching...
No Matches
ObjectFLED.h
Go to the documentation of this file.
1/* ObjectFLED - Teensy 4.x DMA to all pins for independent control of large and
2 multiple LED display objects
3
4 Copyright (c) 2024 Kurt Funderburg
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 OctoWS2811 library code was well-studied and substantial portions of it used
17 to implement high-speed, non-blocking DMA for LED signal output in this library.
18 See ObjectFLED.cpp for a summary of changes made to the original OctoWS2811.
19
20 OctoWS2811 - High Performance WS2811 LED Display Library
21 Copyright (c) 2013 Paul Stoffregen, PJRC.COM, LLC
22 http://www.pjrc.com/teensy/td_libs_OctoWS2811.html
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 THE SOFTWARE.
31*/
32
33#include "platforms/arm/teensy/is_teensy.h"
34
35#ifndef FL_IS_TEENSY_4X
36#error "Sorry, ObjectFLED only works on Teensy 4.x boards."
37#endif
38#if TEENSYDUINO < 121
39#error "Teensyduino version 1.21 or later is required to compile this library."
40#endif
41#ifndef ObjectFLED_h
42#define ObjectFLED_h
43#include <WProgram.h>
44#include "DMAChannel.h"
46
47#include "fl/stl/stdint.h"
48
49//Experimentally found DSE=3, SPEED=0 gave best LED overclocking
50//boot defaults DSE=6, SPEED=2.
51#define OUTPUT_PAD_DSE 3 //Legal values 0-7
52#define OUTPUT_PAD_SPEED 0 //Legal values 0-3
53
54// Ordinary RGB data is converted to GPIO bitmasks on-the-fly using
55// a transmit buffer sized for 2 DMA transfers. The larger this setting,
56// the more interrupt latency OctoWS2811 can tolerate, but the transmit
57// buffer grows in size. For good performance, the buffer should be kept
58// smaller than the half the Cortex-M7 data cache.
59//bitdata[B_P_D * 64] buffer holds data (10KB) for 80 LED bytes: 4DW * 8b = 32DW/LEDB = 96DW/LED
60//framebuffer_index = B_P_D * 2 = pointer to next block for transfer (80 LEDB / bitdata buffer)
61// Doubled from 60 to 120 to lengthen the eDMA major loop on dma2 (the
62// chunked half-buffer used for ESG-chained refill). With BYTES_PER_DMA=60
63// the ISR had only ~1.25 us between dma2's ESG reload and the next TMR4
64// trigger, but the ISR's memset + fillbits + dcache_flush takes ~10 us
65// on Cortex-M7 @ 600 MHz -- so dma2next was reading a partially-refilled
66// chunk on the first ~10 us of each new chunk. That race is the most
67// plausible mechanism behind the residual mid-byte 0->1 phantom bit flips
68// reported in #3406 (statistical analysis shows errors cluster at the
69// 20-LED chunk boundaries that BYTES_PER_DMA=60 produces). 120 doubles
70// the inter-ISR margin with the same memset overhead, +15 KB DMAMEM cost.
71// BYTES_PER_DMA is defined in ObjectFLEDDmaManager.h to keep a single
72// source of truth (CodeRabbit-flagged on PR #3419 -- previously this
73// header also had a #ifndef guard with default 120, while
74// ObjectFLEDDmaManager.h had 150, creating an include-order-dependent
75// ODR hazard between the bitdata[] array size and any consumer that
76// arithmetic-references BYTES_PER_DMA). The definition itself now
77// lives in ObjectFLEDDmaManager.h next to the static_assert and the
78// bitdata array declaration that depends on it.
80
81#define CORDER_RGB 0 //* WS2811, YF923
82#define CORDER_RBG 1
83#define CORDER_GRB 2 //* WS2811B, Most LED strips are wired this way
84#define CORDER_GBR 3 //*
85#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,
86#define CORDER_BGR 5 //* Adafruit Dotstar LEDs SK9822 uses this CO but they use inverted start/stop bits
87#define CORDER_RGBW 6 //* Popular
88#define CORDER_RBGW 7
89#define CORDER_GRBW 8
90#define CORDER_GBRW 9
91#define CORDER_BRGW 10
92#define CORDER_BGRW 11 // Adafruit Dotstar LEDs SK9822 uses this CO but they use inverted start/stop bits
93#define CORDER_WRGB 12
94#define CORDER_WRBG 13
95#define CORDER_WGRB 14
96#define CORDER_WGBR 15
97#define CORDER_WBRG 16
98#define CORDER_WBGR 17
99#define CORDER_RWGB 18
100#define CORDER_RWBG 19
101#define CORDER_GWRB 20
102#define CORDER_GWBR 21
103#define CORDER_BWRG 22
104#define CORDER_BWGR 23
105#define CORDER_RGWB 24
106#define CORDER_RBWG 25
107#define CORDER_GRWB 26
108#define CORDER_GBWR 27
109#define CORDER_BRWG 28
110#define CORDER_BGWR 29
111
112namespace fl {
113
114
115//Usage: ObjectFLED myCube ( Num_LEDs, *drawBuffer, LED_type, numPins, *pinList, serpentineNumber )
117public:
118 // Teensy 4.x hardware ownership:
119 // ObjectFLED owns QTimer4 channels 0-2, XBAR1 DMA request outputs 30/31/94,
120 // the corresponding DMAMUX requests, its allocated DMA channels, and the
121 // selected pins' standard GPIO aliases while an instance is active. It does
122 // not restore prior owners for those resources; conflicting peripherals must
123 // be treated as unsupported while ObjectFLED is in use.
124 // Usage: ObjectFLED myCube ( Num_LEDs, *drawBuffer, LED_type, numPins, *pinList, serpentineNumber )
125 // Example:
126 // byte pinList[NUM_CHANNELS] = {1, 8, 14, 17, 24, 29, 20, 0, 15, 16, 18, 19, 21, 22, 23, 25};
127 // byte pinListBlank[7] = {1, 8, 14, 17, 24, 29, 20};
128 // CRGB testCube[NUM_PLANES][NUM_ROWS][PIX_PER_ROW];
129 // CRGB blankLeds[7][8][8];
130 // ObjectFLED leds(PIX_PER_ROW * NUM_ROWS * NUM_PLANES, testCube, CORDER_RGB, NUM_CHANNELS, pinList);
131 // void setup() {
132 // leds.begin(1.6, 72); //1.6 ocervlock factor, 72uS LED latch delay
133 // leds.setBrightness(64);
134 // }
135 // void loop() {
136 // leds.show();
137 // delay(100);
138 // }
139 ObjectFLED(uint16_t numLEDs, void* drawBuf, uint8_t config, uint8_t numPins, const uint8_t* pinList, \
140 uint8_t serpentine = 0);
141
143
148 template <typename TIMING>
149 void begin(uint16_t latch_delay_us = TIMING::RESET) {
150 // Extract T1, T2, T3 directly from TIMING struct
151 // T1 = high time for '0' bit
152 // T2 = additional high time for '1' bit
153 // T3 = low tail duration
154 begin(TIMING::T1, TIMING::T2, TIMING::T3, latch_delay_us);
155 }
156
163 void begin(uint16_t t1, uint16_t t2, uint16_t t3, uint16_t latch_delay_us = 300);
164
165private:
166 //begin() - Use defalut LED timing: 1.0 OC Factor, 1250 nS CLK (=800 KHz), 300 nS T0H, 750 nS T1H, 300 uS LED Latch Delay.
167 void begin(void);
168
169 //begin(LED_Latch_Delay_uS) - sets the LED Latch Delay.
171
172 //beginInternal(LED_CLK_nS, LED_T0H_nS, LED_T1H_nS, LED_Latch_Delay_uS) - specifies full LED waveform timing.
174
175public:
176
177 void show(void);
180
181 int busy(void);
182
183 //Brightness values 0-255
185
186 //Color Balance is 3-byte number in RGB order. Each byte is a brightness value for that color.
188
190
192
193 // Frame buffer for direct pixel access (used by FastLED integration)
195
196private:
197 static void isr(void);
198
200 void showInternal(bool regenerateFrameBuffer);
201
208public:
210private:
213 uint8_t pinlist[NUM_DIGITAL_PINS];
216 uint16_t TH_TL = 1250; //nS- period of LED output
217 uint16_t T0H = 300; //nS- duration of T0H
218 uint16_t T1H = 750; //nS- duration of T1H
219 uint16_t LATCH_DELAY = 300; //uS time to hold output low for LED latch.
220
221 //for show context switch
222 // Force 32-byte alignment so arm_dcache_flush_delete in begin() operates
223 // on a whole cache line. Without alignment the 16-byte flush is unsafe
224 // per Cortex-M7 cache maintenance semantics (#3406).
225 // #3416 OF-MED-1: bitmaskLocal is 16 bytes (alignas 32 = its own line
226 // start) but the adjacent numpinsLocal/numbytesLocal share the second
227 // half of the same 32-byte cache line. Padding to a full 32 bytes
228 // guarantees the flush_delete invalidates only data this driver owns
229 // and never an adjacent instance's fields.
230 alignas(32) uint32_t bitmaskLocal[8]; // 4 valid words + 4 pad
233 uint8_t pin_bitnumLocal[NUM_DIGITAL_PINS];
234 uint8_t pin_offsetLocal[NUM_DIGITAL_PINS];
235 bool initialized = false;
236}; // class ObjectFLED
237
238
239//fadeToColorBy(RGB_array, LED_count, Color, FadeAmount)
240//Fades an RGB array towards the background color by amount.
242
243
244//drawSquare(RGB_Array, LED_Rows, LED_Cols, Y_Corner, X_Corner, square_Size)
245//Draws square in a 2D RGB array with lower left corner at (Y_Corner, X_Corner).
246//Safe to specify -Y, -X corner, safe to draw a box which partially fits on LED plane.
247void drawSquare(void*, uint16_t, uint16_t, int, int, uint32_t, uint32_t);
248
249} // namespace fl
250
251#endif
void * drawBuffer
Definition ObjectFLED.h:209
uint8_t * frameBufferLocal
Definition ObjectFLED.h:194
void begin(uint16_t t1, uint16_t t2, uint16_t t3, uint16_t latch_delay_us=300)
Three-phase timing begin method (T1, T2, T3 format) This method converts 3-phase timing to ObjectFLED...
uint8_t brightness
Definition ObjectFLED.h:203
uint8_t pin_bitnumLocal[NUM_DIGITAL_PINS]
Definition ObjectFLED.h:233
uint8_t pinlist[NUM_DIGITAL_PINS]
Definition ObjectFLED.h:213
uint32_t update_begin_micros
Definition ObjectFLED.h:202
uint32_t colorBalance
Definition ObjectFLED.h:204
int busy(void)
uint32_t getBalance()
void setBalance(uint32_t)
uint16_t LATCH_DELAY
Definition ObjectFLED.h:219
void genFrameBuffer(uint32_t)
ObjectFLED(uint16_t numLEDs, void *drawBuf, uint8_t config, uint8_t numPins, const uint8_t *pinList, uint8_t serpentine=0)
uint32_t gLevel
Definition ObjectFLED.h:206
uint8_t getBrightness()
void waitForDmaToFinish()
static void isr(void)
uint16_t stripLen
Definition ObjectFLED.h:211
uint8_t serpNumber
Definition ObjectFLED.h:215
void setBrightness(uint8_t)
void showRawFrameBuffer(void)
uint16_t TH_TL
Definition ObjectFLED.h:216
uint32_t rLevel
Definition ObjectFLED.h:205
uint32_t bitmaskLocal[8]
Definition ObjectFLED.h:230
void begin(uint16_t latch_delay_us=TIMING::RESET)
Template-based begin method - extracts timing from TIMING struct at compile-time This is the preferre...
Definition ObjectFLED.h:149
void begin(void)
void begin(uint16_t)
void show(void)
uint32_t numbytesLocal
Definition ObjectFLED.h:232
uint16_t comp1load[3]
Definition ObjectFLED.h:214
uint8_t numpinsLocal
Definition ObjectFLED.h:231
void beginInternal(uint16_t, uint16_t, uint16_t, uint16_t=300)
uint8_t pin_offsetLocal[NUM_DIGITAL_PINS]
Definition ObjectFLED.h:234
void showInternal(bool regenerateFrameBuffer)
uint32_t bLevel
Definition ObjectFLED.h:207
void drawSquare(void *, uint16_t, uint16_t, int, int, uint32_t, uint32_t)
void fadeToColorBy(void *, uint16_t, uint32_t, uint8_t)
Base definition for an LED controller.
Definition crgb.hpp:179
unsigned char uint8_t
Definition stdint.h:208
fl::u32 uint32_t
Definition stdint.h:218
fl::u16 uint16_t
Definition stdint.h:213