* Updated default LED waveform timing to fix compatibility problem with Audio library, and to work with wider selection of LEDs out-of-the-box.
* Updated overclock logic. * Changed .begin() to use OC factor or waveform timing specs, but not both.
This commit is contained in:
+17
-14
@@ -94,21 +94,24 @@ public:
|
||||
ObjectFLED(uint16_t numLEDs, void* drawBuf, uint8_t config, uint8_t numPins, const uint8_t* pinList, \
|
||||
uint8_t serpentine = 0);
|
||||
|
||||
~ObjectFLED() { delete frameBuffer; }
|
||||
~ObjectFLED() {
|
||||
// Wait for prior xmission to end, don't need to wait for latch time before deleting buffer
|
||||
while (micros() - update_begin_micros < numbytes * 8 * TH_TL / OC_FACTOR / 1000 + 5);
|
||||
delete frameBuffer;
|
||||
}
|
||||
|
||||
//begin() - Use defalut LED timing: 1.0 OC Factor, 1250 nS CLK (=800 KHz), 417 nS T0H, 834 nS T1H, 70 uS LED Latch Delay.
|
||||
//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.
|
||||
void begin(void);
|
||||
|
||||
//begin(LED_Overclock_Factor) - divides default 1250 nS LED CLK (=800 KHz), 417 nS T0H, 834 nS T1H.
|
||||
void begin(float);
|
||||
//begin(LED_Latch_Delay_uS) - sets the LED Latch Delay.
|
||||
void begin(uint16_t);
|
||||
|
||||
//begin(LED_Overclock_Factor, LED_Latch_Delay_uS) - divides default 1250 nS LED CLK (=800 KHz),
|
||||
// 417 nS T0H, 834 nS T1H; and sets the LED Latch Delay.
|
||||
void begin(float, uint16_t);
|
||||
// 300 nS T0H, 750 nS T1H; and optionally sets the LED Latch Delay.
|
||||
void begin(double, uint16_t = 300);
|
||||
|
||||
//begin(LED_Overclock_Factor, LED_CLK_nS, LED_T0H_nS, LED_T1H_nS, LED_Latch_Delay_uS) -
|
||||
//specifies full LED timing. Values given for CLK, T0H, T1H are divided by OC Factor.
|
||||
void begin(float, uint16_t, uint16_t, uint16_t, uint16_t);
|
||||
//begin(LED_CLK_nS, LED_T0H_nS, LED_T1H_nS, LED_Latch_Delay_uS) - specifies full LED waveform timing.
|
||||
void begin(uint16_t, uint16_t, uint16_t, uint16_t = 300);
|
||||
|
||||
void show(void);
|
||||
|
||||
@@ -151,11 +154,11 @@ private:
|
||||
uint8_t pinlist[NUM_DIGITAL_PINS];
|
||||
uint16_t comp1load[3];
|
||||
uint8_t serpNumber;
|
||||
float OC_FACTOR = 1.0; //used to reduce period of LED output
|
||||
uint16_t TH_TL = 1250; //nS- period of LED output
|
||||
uint16_t T0H = TH_TL / 3; //nS- duration of T0H
|
||||
uint16_t T1H = TH_TL * 2 / 3; //nS- duration of T1H
|
||||
uint16_t LATCH_DELAY = 75; //uS time to hold output low for LED latch.
|
||||
float OC_FACTOR = 1.0; //used to reduce period of LED output
|
||||
uint16_t TH_TL = 1250; //nS- period of LED output
|
||||
uint16_t T0H = 300; //nS- duration of T0H
|
||||
uint16_t T1H = 750; //nS- duration of T1H
|
||||
uint16_t LATCH_DELAY = 300; //uS time to hold output low for LED latch.
|
||||
|
||||
//for show context switch
|
||||
uint32_t bitmaskLocal[4];
|
||||
|
||||
+12
-11
@@ -53,6 +53,8 @@ GOIO9List = { 2, 3, 4, 5, 29, 33, 48, 49, 50, 51, 52, 53, 54 } //6 top, 7 botto
|
||||
* 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
|
||||
* New default values for TH_TL, T0H, T1H, LATCH_DELAY to work with Audio lib and more LED types
|
||||
* Added wait for prior xmission to complete in destructor
|
||||
*/
|
||||
|
||||
#ifndef __IMXRT1062__
|
||||
@@ -114,21 +116,20 @@ static volatile uint32_t *standard_gpio_addr(volatile uint32_t *fastgpio) {
|
||||
}
|
||||
|
||||
|
||||
void ObjectFLED::begin(float OCF) {
|
||||
OC_FACTOR = OCF;
|
||||
begin();
|
||||
}
|
||||
|
||||
|
||||
void ObjectFLED::begin(float OCF, uint16_t latchDelay) {
|
||||
OC_FACTOR = OCF;
|
||||
void ObjectFLED::begin(uint16_t latchDelay) {
|
||||
LATCH_DELAY = latchDelay;
|
||||
begin();
|
||||
}
|
||||
|
||||
|
||||
void ObjectFLED::begin(float OCF, uint16_t period, uint16_t t0h, uint16_t t1h, uint16_t latchDelay) {
|
||||
OC_FACTOR = OCF;
|
||||
void ObjectFLED::begin(double OCF, uint16_t latchDelay) {
|
||||
OC_FACTOR = (float)OCF;
|
||||
LATCH_DELAY = latchDelay;
|
||||
begin();
|
||||
}
|
||||
|
||||
|
||||
void ObjectFLED::begin(uint16_t period, uint16_t t0h, uint16_t t1h, uint16_t latchDelay) {
|
||||
TH_TL = period;
|
||||
T0H = t0h;
|
||||
T1H = t1h;
|
||||
@@ -173,7 +174,7 @@ void ObjectFLED::begin(void) {
|
||||
// Set up 3 timers to create waveform timing events
|
||||
comp1load[0] = (uint16_t)((float)F_BUS_ACTUAL / 1000000000.0 * (float)TH_TL / OC_FACTOR );
|
||||
comp1load[1] = (uint16_t)((float)F_BUS_ACTUAL / 1000000000.0 * (float)T0H / OC_FACTOR );
|
||||
comp1load[2] = (uint16_t)((float)F_BUS_ACTUAL / 1000000000.0 * (float)T1H / OC_FACTOR );
|
||||
comp1load[2] = (uint16_t)((float)F_BUS_ACTUAL / 1000000000.0 * (float)T1H / (1.0 + ((OC_FACTOR - 1.0)/3)) );
|
||||
TMR4_ENBL &= ~7;
|
||||
TMR4_SCTRL0 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE | TMR_SCTRL_MSTR;
|
||||
TMR4_CSCTRL0 = TMR_CSCTRL_CL1(1) | TMR_CSCTRL_TCF1EN;
|
||||
|
||||
@@ -11,11 +11,12 @@ overclock factor, 256 LED per pin x 16 pins = 4096 LEDs total at 204 back-to-bac
|
||||
ObjectFLED works with FastLED arrays of CRGB, or other drawing buffer in RGB 3-byte format.
|
||||
|
||||
### Glossary:
|
||||
|
||||
* "LED object" or "display object" refers to the ObjectFLED display object(s) in your code.
|
||||
* "LED device" refers to physical LEDs: strings, planes, cubes, etc.
|
||||
* "Segment" refers to physical LEDs connected to a single pin. This can be a group of LED devices
|
||||
(physically daisy-chained) or a subset of LED devices in a larger LED device (rows of a plane,
|
||||
planes of a cube, a single string of house lights, an orbit of an electron, etc.)
|
||||
* "Segment" refers to physical LEDs connected to a single pin. This can be a string or a group
|
||||
of LED devices (physically daisy-chained), or a subset of LED devices in a larger LED device (rows of a plane,
|
||||
planes of a cube, etc.
|
||||
|
||||
## SUPPORTED
|
||||
|
||||
@@ -29,14 +30,13 @@ 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. It is also possible to define 2
|
||||
display objects to display the same drawing buffer on 2 different LED devices.
|
||||
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
|
||||
parallelism allows for multi-fold increase in refresh rate. ObjectFLED automatically breaks your
|
||||
drawing buffer into segments and writes to the pins simultaneously in the specified order. Simply
|
||||
define an ordered pin list for your object, in the same order they are connected physically to the
|
||||
segments in your LED device. ObjectFLED performs segmentation "under the covers".
|
||||
* Large LED devices can be driven with parallel output to separate segments of the device, allowing
|
||||
for multi-fold increase in refresh rate. ObjectFLED breaks your drawing buffer into segments and
|
||||
writes them to the pins simultaneously in the specified order. Simply define an ordered pin list
|
||||
for your object, in the same order they are connected physically to the segments in your LED device.
|
||||
|
||||
* ObjectFLED works with arrays of CRGB for full compatibility with the rich suite of LED graphics
|
||||
functions of FastLED. But you can use any memory object for drawing buffer, so long as it is 3-
|
||||
@@ -44,7 +44,10 @@ 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).
|
||||
(and highest back-to-back refresh rate). ObjectFLED sends a latch pulse at the end of every frame,
|
||||
and defaults to a 300 uS latch period. Some WS2812s specify only 50 uS latch period. To make a
|
||||
noticable increase in refresh rate, try 75 uS latch if yours are rated for 50 (I had to use 72 on a
|
||||
50 uS latch LED).
|
||||
|
||||
* 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.
|
||||
@@ -68,15 +71,12 @@ 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, and simultaneously.
|
||||
list which matches the order in which the pins connect to the device.
|
||||
|
||||
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
|
||||
75uS latch delay (Note that for tested WS2812's, which specify 50uS latch, I had to use 72, perhaps
|
||||
because of added CPU overhead). Use the begin( params ) function on an ObjectFLED object in order
|
||||
to use timing specs from your LED's datasheet. Specify the color order when you instantiate
|
||||
ObjectFLED.
|
||||
300uS latch delay. Use the begin(params) function on an ObjectFLED object in order to use timing specs
|
||||
from your LED's datasheet. Specify the color order when you instantiate ObjectFLED.
|
||||
|
||||
|
||||
## USAGE
|
||||
@@ -106,24 +106,25 @@ where Z is plane, Y is row, X is pixel in row.
|
||||
Use variable names which partially match for creating a drawing array and it's matching display
|
||||
object. Ex.-
|
||||
|
||||
CRGB grid4[Y][X]; ObjectFLED dspGrid4( Y*X, grid4, etc. );
|
||||
CRGB grid4[Y][X];
|
||||
ObjectFLED dspGrid4( Y*X, grid4, etc. );
|
||||
|
||||
|
||||
### begin() FUNCTION
|
||||
|
||||
Called once in setup for the display object
|
||||
|
||||
// Default timing 800KHz clock, 75uS latch delay
|
||||
// Default timing 800KHz clock, 300 nS T0H, 750 nS T1H, and 300 uS latch delay
|
||||
begin(void);
|
||||
|
||||
// Overclock default timing by the given factor
|
||||
begin(float OCF);
|
||||
// Override the default latch delay
|
||||
begin(uint16_t latchDelay);
|
||||
|
||||
// Overclock default timing and overrde default latch delay
|
||||
begin(float OCF, uint16_t latchDelay);
|
||||
// Overclock default timing and optionally overrde default latch delay
|
||||
begin(double OCF, uint16_t latchDelay = 300);
|
||||
|
||||
// Fully specify output waveform timing. NOTE: Given period, t0h, t1h are divided by given OCF.
|
||||
begin(float OCF, uint16_t period, uint16_t t0h, uint16_t t1h, uint16_t latchDelay);
|
||||
// Fully specify output waveform timing TH_TL (clk period), T0H, T1H, and optionally Latch Delay_
|
||||
begin(uint16_t period, uint16_t t0h, uint16_t t1h, uint16_t latchDelay = 300);
|
||||
|
||||
- OCF = Overclocking factor multiples the clock rate (by dividing the pulse width values below)
|
||||
- period = nS time for duration of a full LED data pulse (from LED datasheet) NOTE: For 800KHz clock,
|
||||
@@ -131,14 +132,11 @@ period = 1250nS. This is the default setting.
|
||||
- t0h = nS time for duration of high portion of pulse for LED data 0 (from LED datasheet)
|
||||
- t1h = nS time for duration of high portion of pulse for LED data 1 (from LED datasheet)
|
||||
- latchDelay = uS time to hold data low for LEDs to latch color data to DACs (from LED datasheet)
|
||||
NOTE: In test I had to use 72uS latch delay for LEDs with a spec of 50uS, in order to stop
|
||||
a severe display glitch. I've read at least one LED model specifies 300uS latch. If you
|
||||
get display glitches on a new LED type, latch time should be the first thing to check.
|
||||
|
||||
**Example:**
|
||||
|
||||
dispCube.begin(1.5, 72); //overclocks by factor 1.5 (1200KHz) and sets 72uS latch delay
|
||||
dispVid.begin(1.68, 1250, 420, 840, 72); //420nS, 840nS are 1/3, 2/3 of period
|
||||
dispVid.begin(1250, 420, 840, 72); //420nS, 840nS are longer than typical
|
||||
|
||||
|
||||
### show() FUNCTION
|
||||
@@ -166,7 +164,7 @@ drawing buffer.
|
||||
|
||||
* setBrightness(uint8_t);
|
||||
|
||||
* getBrightness() { return uint8_t brightness; }
|
||||
* uint8_t getBrightness();
|
||||
|
||||
|
||||
### setBalance(), getBalance() FUNCTIONS
|
||||
@@ -176,7 +174,7 @@ Like brightness, this is applied by show() to frame buffer, not to your drawing
|
||||
|
||||
* setBalance(uint32_t);
|
||||
|
||||
* getBalance() { return uint32_t colorBalance; }
|
||||
* uint32_t getBalance();
|
||||
|
||||
|
||||
## ACCESSORY FUNCTIONS
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
### Release 1.1.0
|
||||
* Changed default LED waveform timing to fix conflict with Teensy Audio library and possibly other DMA-enabled apps.
|
||||
More relaxed default timing allows ObjectFLED to work out-of-the-box with more LED chips as well.
|
||||
* Eliminated using both overclock factor and pulse timing specs in same .begin() function call. Either specify OC factor,
|
||||
or pulse timing values, but not both. See mouseover help or OctoFLED.h for the updated .begin() signatures. Only those
|
||||
using the full form of begin(OC_Factor, THTL, T0H, T1H, Latch_Delay) will need to update their .begin() call.
|
||||
* Changed how OC factor is applied to waveform timing. Originally, OC factor was applied to equally shrink TH_TL, T0H,
|
||||
and T1H. Now, OC factor applies to TH_TL and T0H equally, but only reduces T1H by 1/3 of the amount. This is because
|
||||
LED chips have a fixed threshold for when a H pulse is a 0 or a 1. This change yeilded slightly better overlockability
|
||||
in testing with WS2812B chips._
|
||||
|
||||
### Release 1.0.3
|
||||
* Added support for GBR, BGR color formats.
|
||||
|
||||
### Release 1.0.2
|
||||
* Set DSE=3 on output pins improved LED overclocking by 7% (boot default DSE=6).
|
||||
|
||||
### Release 1.0.1
|
||||
* Updated includes to replace include Arduino.h.
|
||||
* Started making releases, added INSTALLATION.md file.
|
||||
* Tweakage to readme.
|
||||
@@ -58,7 +58,7 @@ void setup() {
|
||||
|
||||
//"electron orbit" around 3 4x4 planes driven by 3 pins
|
||||
//1.68 OC factor with these timing values are max OC for YF923's I found posing as WS2812B's
|
||||
electron.begin(1.68, 1250, 420, 840, 72);
|
||||
electron.begin(1.6, 72);
|
||||
electron.setBrightness(brightness);
|
||||
electron.setBalance(0xdae0ff);
|
||||
fill_solid(electronLED[0][0], NUM_LEDS, background);
|
||||
|
||||
@@ -15,8 +15,6 @@ const int PIX_PER_ROW = 16,
|
||||
NUM_PLANES = 16,
|
||||
NUM_CHANNELS = 16,
|
||||
COLOR_ORDER = RGB,
|
||||
//LED baud * 3 bits/LED byte = Serial baud; 2.4 MHz serial, 3.6 passed testing
|
||||
LED_SERIAL_BAUD = 800 * 1.8, //1200, //SerialFLED in kHz
|
||||
STD_OUT_BAUD = 100000;
|
||||
const CRGB background = 0x505000;
|
||||
byte pinList[NUM_CHANNELS] = {1, 8, 14, 17, 24, 29, 20, 0, 15, 16, 18, 19, 21, 22, 23, 25};
|
||||
@@ -49,7 +47,7 @@ void setup() {
|
||||
// FastLED.setCorrection(0xB0E0FF);
|
||||
fill_solid(blankLeds[0][0], 7*8*8, 0x0);
|
||||
fill_solid(testCube[0][0], NUM_PLANES * NUM_ROWS * PIX_PER_ROW, background);
|
||||
leds.begin(1.6, 72); //1.6 ocervlock factor, 72uS LED latch delay
|
||||
leds.begin(); // Use alternate forms of this function to overclock
|
||||
leds.setBrightness(6);
|
||||
leds.setBalance(0xDAE0FF);
|
||||
|
||||
@@ -82,7 +80,7 @@ void loop() {
|
||||
leds.show();
|
||||
leds.show();
|
||||
stopT = micros();
|
||||
Serial.printf("LEDs/channel: %d Serial avg/20 time: %d uS %f fps\n", \
|
||||
Serial.printf("LEDs/channel: %d ObjectFLED avg/20 time: %d uS %f fps\n", \
|
||||
PIX_PER_ROW*NUM_ROWS*NUM_PLANES/NUM_CHANNELS,
|
||||
(stopT - startT) / 20, 20000000.0 / (stopT - startT));
|
||||
while (Serial.read() == -1);
|
||||
@@ -90,7 +88,7 @@ void loop() {
|
||||
startT = micros();
|
||||
leds.show();
|
||||
stopT = micros();
|
||||
Serial.printf("LEDs/channel: %d Serial 1 frame time: %d uS %f fps\n", \
|
||||
Serial.printf("LEDs/channel: %d ObjectFLED 1 frame time: %d uS %f fps\n", \
|
||||
PIX_PER_ROW*NUM_ROWS*NUM_PLANES/NUM_CHANNELS,
|
||||
(stopT - startT), 1000000.0 / (stopT - startT));
|
||||
while (Serial.read() == -1);
|
||||
@@ -121,7 +119,7 @@ return;
|
||||
FastLED.show();
|
||||
FastLED.show();
|
||||
stopT = micros();
|
||||
Serial.printf("LEDs/channel: %d FLED avg/20 time: %d uS %f fps\n", \
|
||||
Serial.printf("LEDs/channel: %d FastLED avg/20 time: %d uS %f fps\n", \
|
||||
PIX_PER_ROW*NUM_ROWS*NUM_PLANES/NUM_CHANNELS,
|
||||
(stopT - startT) / 20, 20000000.0 / (stopT - startT));
|
||||
//Serial.printf("CPU temp: %.1f C %.1f F\n", tempmonGetTemp(), tempmonGetTemp() * 9.0 / 5.0 + 32);
|
||||
@@ -130,7 +128,7 @@ return;
|
||||
startT = micros();
|
||||
FastLED.show();
|
||||
stopT = micros();
|
||||
Serial.printf("LEDs/channel: %d FLED 1 frame time: %d uS %f fps\n", \
|
||||
Serial.printf("LEDs/channel: %d FastLED 1 frame time: %d uS %f fps\n", \
|
||||
PIX_PER_ROW*NUM_ROWS*NUM_PLANES/NUM_CHANNELS,
|
||||
(stopT - startT), 1000000.0 / (stopT - startT));
|
||||
while (Serial.read() == -1);
|
||||
|
||||
Reference in New Issue
Block a user