Hallo zusammen,
ich habe vor gut 10 Jahren einen LED Coffee Table gebaut.
Der fristet nun sein Dasein ungenutzt, vor sich hin.
Es wurden LED´s mit LPD6803 von Bliptronics verbaut, welche die LEDPixels Library verwendet haben.
Mein Wiederbelebungsversuch ist natürlich nun daran gescheitert, dass es die
- avr/io.h
- avr/interrupt.h
auf dem ESP32 natürlich nicht gibt.
Deshalb meine Hoffnung, dass einer von Euch Profis mir weiterhelfen kann eine Alternative zu finden.
Oder natürlich mich soweit erleuchtet, dass ich den Kommunikationslayer neu machen kann.
LEDPixels.cpp (Reduziert, vollständig im Anhang)
/* LEDPixels.cpp - A Library for use with LED Pixels using the LPD6803 Controller chip */
#include "LEDPixels.h"
#include "glcdfont.c"
char clockPin = 12; //GREEN wire
char dataPin = 11; //YELLOW wire
char NoOfLEDs = 100; //Total number of LEDs in your string.
// Globals used by interrupt code.
char SendMode=0; // Used in interrupt 0=start,1=header,2=data,3=data done
char BitCount=0; // Used in interrupt
unsigned int LedIndex=0; // Used in interrupt - Which LED we are sending.
char BlankCounter=0; //Used in interrupt.
unsigned int BitMask; //Used in interrupt.
//Display[] array holds the 15 bit RGB values for each LED.
int * Display;
LEDPixels LP1; //Preinstatiate
ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
LP1.doOutput();
}
LEDPixels::LEDPixels()
{
//Set the pins to use here
}
void LEDPixels::doOutput()
{
switch(SendMode)
{
case 3: //Done..just send clocks with zero data
digitalWrite(dataPin, 0); //You'll need 255 clocks for a LED to diplsay 1 color pwm.
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
break;
case 2: //Sending Data
if (BitCount==0) //First bit is always 1 followed by 15 bits of LED color.
{ digitalWrite(dataPin, 1);
BitMask=0x8000;//Init bit mask
}
else if(BitMask & Display[LedIndex]) //If not the first bit then output the next bits (Starting with MSB bit 15 down.)
digitalWrite(dataPin, 1);
else
digitalWrite(dataPin, 0);
BitMask>>=1;
BitCount++;
if(BitCount == 16) //Last bit?
{
LedIndex++; //Move to next LED
if (LedIndex < NoOfLEDs) //Still more leds to go or are we done?
{
BitCount=0; //Start from the fist bit of the next LED
}
else
SendMode=3; //No more LEDs to go, we are done!
}
// Clock out data.
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
break;
case 1: //Header
if (BitCount < 32)
{
digitalWrite(dataPin, 0);
BitCount++;
if(BitCount==32)
{
SendMode++; //If this was the last bit of header then move on to data.
LedIndex=0;
BitCount=0;
}
}
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
break;
case 0: //Start
if(!BlankCounter) //AS SOON AS CURRENT pwm IS DONE. BlankCounter
{
BitCount=0;
LedIndex=0;
SendMode=1;
}
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
break;
}
//Keep track of where the LEDs are at in their pwm cycle.
BlankCounter++;
}
unsigned int LEDPixels::Translate(unsigned int x,unsigned int y)
{
if(x%2)
return(((x+1) * gridHeight)- 1 - y);
else
return((x * gridHeight) + y);
}
void LEDPixels::setPixel(unsigned int x, unsigned int y, unsigned int color)
{
Display[Translate(y,x)]=color;
}
//Swap the values of two variables, for use when drawing lines.
void LEDPixels::swap(unsigned int * a, unsigned int * b)
{
int temp;
temp=*b;
*b=*a;
*a=temp;
}
void LEDPixels::setCursor(uint8_t x, uint8_t y) {
cursor_x = x;
cursor_y = y;
}
void LEDPixels::setRange(unsigned int startLED, unsigned int endLED, unsigned int color )
{
// set a linear range of LEDs. The color value must be created with the Color function (15 bit rgb)
while(startLED <= endLED)
Display[startLED++]=color;
}
// Set a LED, give it r,g,b
void LEDPixels::setLEDFast(unsigned int LED, byte rr, byte gg, byte bb)
{
if(LED < NoOfLEDs)
//Display[LED] = color(bb,rr,gg);
Display[LED] = color(rr,gg,bb);
}
// set an LED but just pass it a 15 bit color value
void LEDPixels::setLEDFast(unsigned int LED, unsigned int color)
{
if(LED < NoOfLEDs)
Display[LED] = color;
}
// Create a 15 bit color value from R,G,B
unsigned int LEDPixels::color(unsigned char r,unsigned char g,unsigned char b)
{
//Take the lowest 5 bits of each value and append them end to end
return( ((unsigned int)r & 0x1F )<<10 | ((unsigned int)g & 0x1F)<<5 | (unsigned int)b & 0x1F);
}
void LEDPixels::show()
{
// The interrupt routine will see this as re-send LED color data.
SendMode = 0;
}
void LEDPixels::initialize(long microseconds, int * DisplayAddress,unsigned int LEDCount , char clkPin, char dPin )
{
byte Counter;
clockPin = clkPin;
dataPin = dPin;
Display = DisplayAddress;
NoOfLEDs = LEDCount;
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
show(); // Kick off display.
TCCR1A = 0; // clear control register A
TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
if(microseconds > 0) setPeriod(microseconds);
//isrCallback = isr; // register the user's callback with the real ISR
TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
sei(); // ensures that interrupts are globally enabled
start();
}
void LEDPixels::setPeriod(long microseconds)
{
long cycles = (F_CPU * microseconds) / 2000000; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
TCCR1B |= clockSelectBits; // reset clock select register
}
void LEDPixels::detachInterrupt()
{
TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit
}
void LEDPixels::start()
{
TCCR1B |= clockSelectBits;
}
void LEDPixels::stop()
{
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits
}
void LEDPixels::restart()
{
TCNT1 = 0;
}
Das müsste doch eine SPI-Schnittstelle sein, oder?
FastLED wäre die Lösung, wenn dort nicht explizit stehen würde:
LPD6803, HL1606, and "595"-style shift registers are no longer supported by the library. The older Version 1 of the library ("FastSPI_LED") has support for these, but is missing many of the advanced features of current versions and is no longer being maintained.
Version 1 unterstützt aber noch keinen ESP ![]()
glcdfont.c (8.35 KB)
keywords.txt (462 Bytes)
LEDPixels.cpp (12.9 KB)
LEDPixels.h (3.08 KB)
