diff --git a/src/extras/Pixel.cpp b/src/extras/Pixel.cpp index b79c8c6..3d16e29 100644 --- a/src/extras/Pixel.cpp +++ b/src/extras/Pixel.cpp @@ -9,13 +9,16 @@ // Single-Wire RGB/RGBW NeoPixels // //////////////////////////////////////////// -Pixel::Pixel(int pin, pixel_type_t pType){ +Pixel::Pixel(int pin, boolean isRGBW){ rf=new RFControl(pin,false,false); // set clock to 1/80 usec, no default driver if(!*rf) return; - this->pType=pType; + if(isRGBW) + this->lastBit=0; + else + this->lastBit=8; setTiming(0.32, 0.88, 0.64, 0.56, 80.0); // set default timing parameters (suitable for most SK68 and WS28 RGB pixels) @@ -43,32 +46,13 @@ void Pixel::setTiming(float high0, float low0, float high1, float low1, uint32_t /////////////////// -void Pixel::setRGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint32_t nPixels){ - - if(!*rf || nPixels==0) - return; - - uint32_t data=getColorRGB(r,g,b,w); - setColors(&data,nPixels,false); -} - -/////////////////// - -void Pixel::setHSV(float h, float s, float v, double w, uint32_t nPixels){ - float r,g,b; - LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b); - setRGB(r*255,g*255,b*255,w*2.555,nPixels); -} - -/////////////////// - -void Pixel::setColors(const uint32_t *data, uint32_t nPixels, boolean multiColor){ +void Pixel::set(Color *c, int nPixels, boolean multiColor){ if(!*rf || nPixels==0) return; status.nPixels=nPixels; - status.data=data; + status.color=c; status.iMem=0; status.iBit=32; status.started=true; @@ -86,17 +70,21 @@ void Pixel::setColors(const uint32_t *data, uint32_t nPixels, boolean multiColor /////////////////// -uint32_t Pixel::getColorRGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w){ -// return(g<<16 | r<<8 | b); - return(g<<24 | r<<16 | b<<8 | w); +Pixel::Color Pixel::RGB(uint8_t red, uint8_t green, uint8_t blue, uint8_t white){ + Color x; + x.red=red; + x.green=green; + x.blue=blue; + x.white=white; + return(x); } /////////////////// -uint32_t Pixel::getColorHSV(float h, float s, float v, double w){ +Pixel::Color Pixel::HSV(float h, float s, float v, double w){ float r,g,b; LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b); - return(getColorRGB(r*255,g*255,b*255,w*2.555)); + return(RGB(r*255,g*255,b*255,w*2.555)); } /////////////////// @@ -117,11 +105,11 @@ void IRAM_ATTR Pixel::loadData(void *arg){ } for(int i=0;i<8;i++) - RMTMEM.chan[status.px->rf->getChannel()].data32[status.iMem++].val=status.px->pattern[(*status.data>>(--status.iBit))&1]; + RMTMEM.chan[status.px->rf->getChannel()].data32[status.iMem++].val=status.px->pattern[(status.color->val>>(--status.iBit))&1]; - if(status.iBit==status.px->pType){ + if(status.iBit==status.px->lastBit){ status.iBit=32; - status.data+=status.multiColor; + status.color+=status.multiColor; status.nPixels--; } @@ -190,8 +178,7 @@ void Dot::set(Color *c, int nPixels, boolean multiColor){ *clockSetReg=clockMask; *clockClearReg=clockMask; } - if(multiColor) - c++; + c+=multiColor; } *dataClearReg=dataMask; // send all zeros @@ -213,13 +200,12 @@ Dot::Color Dot::RGB(uint8_t red, uint8_t green, uint8_t blue, uint8_t drive){ return(x); } - /////////////////// -Dot::Color Dot::HSV(float h, float s, float v, float level){ +Dot::Color Dot::HSV(float h, float s, float v, double level){ float r,g,b; LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b); - return(RGB(r*255,g*255,b*255,level/100*31.5)); + return(RGB(r*255,g*255,b*255,level*0.315)); } //////////////////////////////////////////// diff --git a/src/extras/Pixel.h b/src/extras/Pixel.h index bb45bf0..37708be 100644 --- a/src/extras/Pixel.h +++ b/src/extras/Pixel.h @@ -14,16 +14,23 @@ class Pixel { - public: - enum pixel_type_t { - RGB=8, - RGBW=0 - }; - + public: + struct Color { + union{ + struct { + uint8_t white:8; + uint8_t blue:8; + uint8_t red:8; + uint8_t green:8; + }; + uint32_t val; + }; + }; + private: struct pixel_status_t { int nPixels; - const uint32_t *data; + Color *color; int iBit; int iMem; boolean started; @@ -36,7 +43,7 @@ class Pixel { uint32_t resetTime; // minimum time (in usec) between pulse trains uint32_t txEndMask; // mask for end-of-transmission interrupt uint32_t txThrMask; // mask for threshold interrupt - pixel_type_t pType; // type of Pixel (RGB or RGBW) + uint32_t lastBit; // 0=RGBW; 8=RGB const int memSize=sizeof(RMTMEM.chan[0].data32)/4; // determine size (in pulses) of one channel @@ -44,19 +51,15 @@ class Pixel { volatile static pixel_status_t status; // storage for volatile information modified in interupt handler public: - Pixel(int pin, pixel_type_t pType=RGB); // creates addressable single-wire RGB or RGBW LED on pin (such as the SK68 or WS28) - - void setTiming(float high0, float low0, float high1, float low1, uint32_t lowReset); // changes default timings for bit pulse - note parameters are in MICROSECONDS - - void setRGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0, uint32_t nPixels=1); // sets color of nPixels to RGB(W) values (0-255) - void setHSV(float h, float s, float v, double w=0, uint32_t nPixels=1); // sets color of nPixels to HSV(W) values where h=[0,360], s/v/w=[0,100] - void setColors(const uint32_t *data, uint32_t nPixels, bool multiColor=true); // sets colors of nPixels from array of colors stored in data - + Pixel(int pin, boolean isRGBW=false); // creates addressable single-wire RGB (false) or RGBW (true) LED connected to pin (such as the SK68 or WS28) + static Color RGB(uint8_t red, uint8_t green, uint8_t blue, uint8_t white=0); // returns Color based on provided RGB(W) values where r/g/b/w=[0-255] + static Color HSV(float h, float s, float v, double w=0); // returns Color based on provided HSV(W) values where h=[0,360] and s/v/w=[0,100] + void set(Color *c, int nPixels, boolean multiColor=true); // sets colors of nPixels based on array of Colors c; setting multiColor to false repeats Color in c[0] for all nPixels + void set(Color c, int nPixels=1){set(&c,nPixels,false);} // sets color of nPixels to be equal to specific Color c + int getPin(){return(rf->getPin());} // returns pixel pin if valid, else returns -1 - - static uint32_t getColorRGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0); // return pixel Color from RGB(W) values - static uint32_t getColorHSV(float h, float s, float v, double w=0); // return pixel Color from HSV(W) values - + void setTiming(float high0, float low0, float high1, float low1, uint32_t lowReset); // changes default timings for bit pulse - note parameters are in MICROSECONDS + operator bool(){ // override boolean operator to return true/false if creation succeeded/failed return(*rf); } @@ -91,11 +94,11 @@ class Dot { volatile uint32_t *clockClearReg; public: - Dot(uint8_t dataPin, uint8_t clockPin); - void set(Color c, int nPixels=1){set(&c,nPixels,false);} - void set (Color *c, int nPixels, boolean multiColor=true); - static Color RGB(uint8_t red, uint8_t green, uint8_t blue, uint8_t drive=31); - static Color HSV(float h, float s, float v, float level=100); + Dot(uint8_t dataPin, uint8_t clockPin); // creates addressable two-wire RGB LED connected to dataPin and clockPin (such as the DotStar SK9822 or APA102) + static Color RGB(uint8_t red, uint8_t green, uint8_t blue, uint8_t drive=31); // returns Color based on provided RGB values where r/g/b=[0-255] and current-limiting drive=[0,31] + static Color HSV(float h, float s, float v, double level=100); // returns Color based on provided HSV values where h=[0,360], s/v=[0,100], and current-limiting drive=[0,100] + void set(Color *c, int nPixels, boolean multiColor=true); // sets colors of nPixels based on array of Colors c; setting multiColor to false repeats Color in c[0] for all nPixels + void set(Color c, int nPixels=1){set(&c,nPixels,false);} // sets color of nPixels to be equal to specific Color c }; //////////////////////////////////////////// diff --git a/src/extras/extras.ino b/src/extras/extras.ino index 1f94862..991a457 100644 --- a/src/extras/extras.ino +++ b/src/extras/extras.ino @@ -8,9 +8,11 @@ struct Effect1 { int H=0; uint32_t alarmTime=0; uint32_t speed; + uint8_t nPixels; - Effect1(Pixel *px, uint32_t speed=20){ + Effect1(Pixel *px, uint32_t speed, uint8_t nPixels){ this->px=px; + this->nPixels=nPixels; this->speed=speed; } @@ -18,9 +20,9 @@ struct Effect1 { if(millis()setHSV(H,100,100,0,60); + px->set(px->HSV(H,100,10),nPixels); H=(H+1)%360; - + alarmTime=millis()+speed; } }; @@ -31,12 +33,14 @@ struct Effect2 { int phase=0; int dir=1; int H=0; - uint32_t x[60]; + Pixel::Color x[60]; uint32_t alarmTime=0; uint32_t speed; + uint8_t nPixels; - Effect2(Pixel *px, uint32_t speed=20){ + Effect2(Pixel *px, uint32_t speed, uint8_t nPixels){ this->px=px; + this->nPixels=nPixels; this->speed=speed; } @@ -44,23 +48,23 @@ struct Effect2 { if(millis()getColorHSV(H,100,100); - else if(i==59-phase) - x[i]=px->getColorHSV(H+180,100,100); + x[i]=px->HSV(H,100,100); + else if(i==nPixels-1-phase) + x[i]=px->HSV(H+180,100,100); else - x[i]=0; + x[i]=Pixel::HSV(0,0,0); } - px->setColors(x,60); - phase=(phase+dir)%60; + px->set(x,nPixels); + phase=(phase+dir)%nPixels; if(phase==0){ dir=1; H=(H+10)%360; } - else if(phase==59){ + else if(phase==nPixels-1){ dir=-1; H=(H+10)%360; } @@ -69,6 +73,31 @@ struct Effect2 { } }; +struct Effect3 { + + Dot *dot; + int H=0; + uint32_t alarmTime=0; + uint32_t speed; + uint8_t nPixels; + + Effect3(Dot *dot, uint32_t speed, uint8_t nPixels){ + this->dot=dot; + this->nPixels=nPixels; + this->speed=speed; + } + + void update(){ + if(millis()set(Dot::HSV(H,100,100),nPixels); + H=(H+1)%360; + + alarmTime=millis()+speed; + } +}; + #if defined(CONFIG_IDF_TARGET_ESP32C3) #define PIXEL_PIN_1 8 @@ -83,14 +112,17 @@ struct Effect2 { #define PIXEL_PIN_1 23 #define PIXEL_PIN_2 21 + + Dot dot(32,5); #endif -Pixel px1(PIXEL_PIN_1,Pixel::RGBW); -Pixel px2(PIXEL_PIN_2,Pixel::RGBW); +Pixel px1(PIXEL_PIN_1); +Pixel px2(PIXEL_PIN_2,true); -Effect1 effect1(&px1,20); -Effect2 effect2(&px2,20); +Effect1 effect1(&px1,20,8); +Effect2 effect2(&px2,20,60); +Effect3 effect3(&dot,20,30); void setup() { @@ -105,4 +137,5 @@ void setup() { void loop(){ effect1.update(); effect2.update(); + effect3.update(); }