188 lines
7.2 KiB
C++
188 lines
7.2 KiB
C++
/* ObjectFLED - Teensy 4.x DMA to all pins for independent control of large and
|
|
multiple LED display objects
|
|
|
|
Copyright (c) 2024 Kurt Funderburg
|
|
2025 Clément SAILLANT
|
|
=> added setPixel method
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
OctoWS2811 library code was well-studied and substantial portions of it used
|
|
to implement high-speed, non-blocking DMA for LED signal output in this library.
|
|
See ObjectFLED.cpp for a summary of changes made to the original OctoWS2811.
|
|
|
|
OctoWS2811 - High Performance WS2811 LED Display Library
|
|
Copyright (c) 2013 Paul Stoffregen, PJRC.COM, LLC
|
|
http://www.pjrc.com/teensy/td_libs_OctoWS2811.html
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
|
|
#ifndef __IMXRT1062__
|
|
#error "Sorry, ObjectFLED only works on Teensy 4.x boards."
|
|
#endif
|
|
#if TEENSYDUINO < 121
|
|
#error "Teensyduino version 1.21 or later is required to compile this library."
|
|
#endif
|
|
#ifndef ObjectFLED_h
|
|
#define ObjectFLED_h
|
|
#include <WProgram.h>
|
|
#include "DMAChannel.h"
|
|
|
|
//Experimentally found DSE=3, SPEED=0 gave best LED overclocking
|
|
//boot defaults DSE=6, SPEED=2.
|
|
#define OUTPUT_PAD_DSE 3 //Legal values 0-7
|
|
#define OUTPUT_PAD_SPEED 0 //Legal values 0-3
|
|
|
|
// Ordinary RGB data is converted to GPIO bitmasks on-the-fly using
|
|
// a transmit buffer sized for 2 DMA transfers. The larger this setting,
|
|
// the more interrupt latency OctoWS2811 can tolerate, but the transmit
|
|
// buffer grows in size. For good performance, the buffer should be kept
|
|
// smaller than the half the Cortex-M7 data cache.
|
|
//bitdata[B_P_D * 64] buffer holds data (10KB) for 80 LED bytes: 4DW * 8b = 32DW/LEDB = 96DW/LED
|
|
//framebuffer_index = B_P_D * 2 = pointer to next block for transfer (80 LEDB / bitdata buffer)
|
|
#define BYTES_PER_DMA 20 //= number of pairs of LEDB (40=80B) bitmasks in bitdata.
|
|
|
|
#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_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_RGBW 6 //* Popular
|
|
#define CORDER_RBGW 7
|
|
#define CORDER_GRBW 8
|
|
#define CORDER_GBRW 9
|
|
#define CORDER_BRGW 10
|
|
#define CORDER_BGRW 11 // Adafruit Dotstar LEDs SK9822 uses this CO but they use inverted start/stop bits
|
|
#define CORDER_WRGB 12
|
|
#define CORDER_WRBG 13
|
|
#define CORDER_WGRB 14
|
|
#define CORDER_WGBR 15
|
|
#define CORDER_WBRG 16
|
|
#define CORDER_WBGR 17
|
|
#define CORDER_RWGB 18
|
|
#define CORDER_RWBG 19
|
|
#define CORDER_GWRB 20
|
|
#define CORDER_GWBR 21
|
|
#define CORDER_BWRG 22
|
|
#define CORDER_BWGR 23
|
|
#define CORDER_RGWB 24
|
|
#define CORDER_RBWG 25
|
|
#define CORDER_GRWB 26
|
|
#define CORDER_GBWR 27
|
|
#define CORDER_BRWG 28
|
|
#define CORDER_BGWR 29
|
|
|
|
|
|
//Usage: ObjectFLED myCube ( Num_LEDs, *drawBuffer, LED_type, numPins, *pinList, serpentineNumber )
|
|
class ObjectFLED {
|
|
public:
|
|
//Usage: ObjectFLED myCube ( Num_LEDs, *drawBuffer, LED_type, numPins, *pinList, serpentineNumber )
|
|
ObjectFLED(uint16_t numLEDs, void* drawBuf, uint8_t config, uint8_t numPins, const uint8_t* pinList, \
|
|
uint8_t serpentine = 0);
|
|
|
|
~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), 300 nS T0H, 750 nS T1H, 300 uS LED Latch Delay.
|
|
void begin(void);
|
|
|
|
//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),
|
|
// 300 nS T0H, 750 nS T1H; and optionally sets the LED Latch Delay.
|
|
void begin(double, uint16_t = 300);
|
|
|
|
//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);
|
|
|
|
int busy(void);
|
|
|
|
//Brightness values 0-255
|
|
void setBrightness(uint8_t);
|
|
|
|
//Color Balance is 3-byte number in RGB order. Each byte is a brightness value for that color.
|
|
void setBalance(uint32_t);
|
|
|
|
uint8_t getBrightness() { return brightness; }
|
|
|
|
uint32_t getBalance() { return colorBalance; }
|
|
|
|
void setPixel(uint32_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
|
void getPixel(uint32_t index, uint8_t &r, uint8_t &g, uint8_t &b, uint8_t &w);
|
|
|
|
private:
|
|
static void isr(void);
|
|
|
|
void genFrameBuffer(uint32_t);
|
|
|
|
static uint8_t* frameBuffer; //isr()
|
|
static uint32_t numbytes; //isr()
|
|
static uint8_t numpins; //isr()
|
|
static uint8_t pin_bitnum[NUM_DIGITAL_PINS]; //isr()
|
|
static uint8_t pin_offset[NUM_DIGITAL_PINS]; //isr()
|
|
DMAMEM static uint32_t bitdata[BYTES_PER_DMA * 64] __attribute__((used, aligned(32))); //isr()
|
|
DMAMEM static uint32_t bitmask[4] __attribute__((used, aligned(32)));
|
|
static DMAChannel dma1, dma2, dma3;
|
|
static DMASetting dma2next;
|
|
|
|
uint32_t update_begin_micros = 0;
|
|
uint8_t brightness = 255;
|
|
uint32_t colorBalance = 0xFFFFFF;
|
|
uint32_t rLevel = 65025;
|
|
uint32_t gLevel = 65025;
|
|
uint32_t bLevel = 65025;
|
|
void* drawBuffer;
|
|
uint16_t stripLen;
|
|
uint8_t params;
|
|
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 = 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];
|
|
uint8_t numpinsLocal;
|
|
uint8_t* frameBufferLocal;
|
|
uint32_t numbytesLocal;
|
|
uint8_t pin_bitnumLocal[NUM_DIGITAL_PINS];
|
|
uint8_t pin_offsetLocal[NUM_DIGITAL_PINS];
|
|
}; // class ObjectFLED
|
|
|
|
|
|
//fadeToColorBy(RGB_array, LED_count, Color, FadeAmount)
|
|
//Fades an RGB array towards the background color by amount.
|
|
void fadeToColorBy(void*, uint16_t, uint32_t, uint8_t);
|
|
|
|
|
|
//drawSquare(RGB_Array, LED_Rows, LED_Cols, Y_Corner, X_Corner, square_Size)
|
|
//Draws square in a 2D RGB array with lower left corner at (Y_Corner, X_Corner).
|
|
//Safe to specify -Y, -X corner, safe to draw a box which partially fits on LED plane.
|
|
void drawSquare(void*, uint16_t, uint16_t, int, int, uint32_t, uint32_t);
|
|
|
|
#endif |