diff --git a/src/extras/Blinker.h b/src/extras/Blinker.h index 633bc19..b54c4ce 100644 --- a/src/extras/Blinker.h +++ b/src/extras/Blinker.h @@ -25,104 +25,6 @@ * ********************************************************************************/ -#pragma once +#include "../src/extras/Blinker.h" -#include -#include -//////////////////////////////// -// Blinkable Interface // -//////////////////////////////// - -class Blinkable { - public: - - virtual void on()=0; - virtual void off()=0; - virtual int getPin()=0; -}; - -//////////////////////////////// -// Blinker // -//////////////////////////////// - -class Blinker { - - TaskHandle_t blinkHandle = NULL; - Blinkable *led; - - int nBlinks; - int onTime; - int offTime; - int delayTime; - - unsigned long pauseDuration; - unsigned long pauseTime; - boolean isPaused=false; - - static void blinkTask(void *arg); - - public: - - Blinker(Blinkable *led, uint16_t autoOffDuration=0); - -// Creates a generic blinking LED in a separate task thread -// -// led: An initialized LED device that implements the Blinkable Interface -//// -// autoOffDuration: If greater than zero, Blinker will automatically turn off after autoOffDuration (in seconds) has elapsed -// Blinker will resume normal operation upon next call to start(), on(), or off() -// Program must periodically call check() for auto-off functionality to work - - void start(int period, float dutyCycle=0.5); - -// Starts simple ON/OFF blinking. -// -// period: ON/OFF blinking period, in milliseconds -// dutyCycle: Fraction of period that LED is ON (default=50%) - - void start(int period, float dutyCycle, int nBlinks, int delayTime); - -// Starts ON/OFF blinking pattern. -// -// period: ON/OFF blinking period, in milliseconds, used for blinking portion of pattern -// dutyCycle: Fraction of period that LED is ON (default=50%) -// nBlinks: Number of blinks in blinking portion of pattern -// delayTime: delay, in milliseconds, during which LED is off before restarting blinking pattern - - void stop(); - -// Stops current blinking pattern. - - void on(); - -// Stops current blinking pattern and turns on LED - - void off(); - -// Stops current blinking pattern and turns off LED - - void check(); - -// Optional check to see if LED output should be paused (check is bypassed if pauseDuration=0) - - int getPin(); - -// Returns pin number of connected LED - -}; - -//////////////////////////////// -// GenericLED // -//////////////////////////////// - -class GenericLED : public Blinkable { - int pin; - - public: - - GenericLED(int pin) : pin{pin} {pinMode(pin,OUTPUT);digitalWrite(pin,0);} - void on() {digitalWrite(pin,HIGH);} - void off() {digitalWrite(pin,LOW);} - int getPin() {return(pin);} -}; diff --git a/src/extras/Pixel.h b/src/extras/Pixel.h index e781129..3bcc8bd 100644 --- a/src/extras/Pixel.h +++ b/src/extras/Pixel.h @@ -25,235 +25,5 @@ * ********************************************************************************/ -//////////////////////////////////////////// -// Addressable LEDs // -//////////////////////////////////////////// +#include "../src/extras/Pixel.h" -#pragma once - -#include "RFControl.h" -#include "PwmPin.h" -#include "Blinker.h" - -//////////////////////////////////////////// -// Single-Wire RGB/RGBW NeoPixels // -//////////////////////////////////////////// - -class Pixel : public Blinkable { - - public: - struct Color { - union{ - struct { - uint8_t white:8; - uint8_t blue:8; - uint8_t red:8; - uint8_t green:8; - }; - uint32_t val; - }; - - Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0){ // returns Color based on provided RGB(W) values where r/g/b/w=[0-255] - this->red=r; - this->green=g; - this->blue=b; - this->white=w; - return(*this); - } - - 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] - float r,g,b; - LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b); - this->red=r*255; - this->green=g*255; - this->blue=b*255; - this->white=w*2.555; - return(*this); - } - - bool operator==(const Color& color){ - return(val==color.val); - } - - bool operator!=(const Color& color){ - return(val!=color.val); - } - - Color operator+(const Color& color){ - Color newColor; - newColor.white=white+color.white; - newColor.blue=blue+color.blue; - newColor.red=red+color.red; - newColor.green=green+color.green; - return(newColor); - } - - Color& operator+=(const Color& color){ - white+=color.white; - red+=color.red; - blue+=color.blue; - green+=color.green; - return(*this); - } - - Color operator-(const Color& color){ - Color newColor; - newColor.white=white-color.white; - newColor.blue=blue-color.blue; - newColor.red=red-color.red; - newColor.green=green-color.green; - return(newColor); - } - - Color& operator-=(const Color& color){ - white-=color.white; - red-=color.red; - blue-=color.blue; - green-=color.green; - return(*this); - } - - }; // Color - - private: - struct pixel_status_t { - int nPixels; - Color *color; - int iBit; - int iMem; - boolean started; - Pixel *px; - boolean multiColor; - }; - - RFControl *rf; // Pixel utilizes RFControl - uint32_t pattern[2]; // storage for zero-bit and one-bit pulses - 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 - uint32_t lastBit; // 0=RGBW; 8=RGB - Color onColor; // color used for on() command - - const int memSize=sizeof(RMTMEM.chan[0].data32)/4; // determine size (in pulses) of one channel - - static void loadData(void *arg); // interrupt handler - volatile static pixel_status_t status; // storage for volatile information modified in interupt handler - - public: - 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) - 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 - - static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0){return(Color().RGB(r,g,b,w));} // an alternative method for returning an RGB Color - static Color HSV(float h, float s, float v, double w=0){return(Color().HSV(h,s,v,w));} // an alternative method for returning an HSV Color - - int getPin(){return(rf->getPin());} // returns pixel pin if valid, else returns -1 - 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); - } - - void on() {set(onColor);} - void off() {set(RGB(0,0,0,0));} - Pixel *setOnColor(Color c){onColor=c;return(this);} -}; - -//////////////////////////////////////////// -// Two-Wire RGB DotStars // -//////////////////////////////////////////// - -class Dot { - - public: - struct Color { - union{ - struct { - uint8_t red:8; - uint8_t green:8; - uint8_t blue:8; - uint8_t drive:5; - uint8_t flags:3; - }; - uint32_t val; - }; - - Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31){ // returns Color based on provided RGB values where r/g/b=[0-255] and current-limiting drive level=[0,31] - this->red=r; - this->green=g; - this->blue=b; - this->drive=driveLevel; - this->flags=7; - return(*this); - } - - Color HSV(float h, float s, float v, double drivePercent=100){ // returns Color based on provided HSV values where h=[0,360], s/v=[0,100], and current-limiting drive percent=[0,100] - float r,g,b; - LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b); - this->red=r*255; - this->green=g*255; - this->blue=b*255; - this->drive=drivePercent*0.315; - this->flags=7; - return(*this); - } - - bool operator==(const Color& color){ - return(val==color.val); - } - - bool operator!=(const Color& color){ - return(val!=color.val); - } - - Color operator+(const Color& color){ - Color newColor; - newColor.blue=blue+color.blue; - newColor.red=red+color.red; - newColor.green=green+color.green; - return(newColor); - } - - Color& operator+=(const Color& color){ - red+=color.red; - blue+=color.blue; - green+=color.green; - return(*this); - } - - Color operator-(const Color& color){ - Color newColor; - newColor.blue=blue-color.blue; - newColor.red=red-color.red; - newColor.green=green-color.green; - return(newColor); - } - - Color& operator-=(const Color& color){ - red-=color.red; - blue-=color.blue; - green-=color.green; - return(*this); - } - - }; - - private: - uint32_t dataMask; - uint32_t clockMask; - volatile uint32_t *dataSetReg; - volatile uint32_t *dataClearReg; - volatile uint32_t *clockSetReg; - volatile uint32_t *clockClearReg; - - public: - 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) - 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 - - static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31){return(Color().RGB(r,g,b,driveLevel));} // an alternative method for returning an RGB Color - static Color HSV(float h, float s, float v, double drivePercent=100){return(Color().HSV(h,s,v,drivePercent));} // an alternative method for returning an HSV Color - -}; - -//////////////////////////////////////////// diff --git a/src/extras/PwmPin.h b/src/extras/PwmPin.h index d9506ec..f012652 100644 --- a/src/extras/PwmPin.h +++ b/src/extras/PwmPin.h @@ -25,77 +25,5 @@ * ********************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ----- PWM Pin Control ----- -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Wrappers around the ESP-IDF ledc library to control PWM-based devices: -// -// LedPin(pin) - controls a Dimmable LED on specified pin with frequency=5000 Hz -// - use set(level) to set brightness from 0-100% -// -// ServoPin(pin) - controls a Servo Motor on specified pin with frequency=50 Hz -// - use set(degrees) to set position to degrees -// -// -///////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include "../src/extras/PwmPin.h" -#pragma once - -#include -#include -#include "Blinker.h" - -#define DEFAULT_PWM_FREQ 5000 - -///////////////////////////////////// - -class LedC { - - protected: - static ledc_channel_config_t *channelList[LEDC_CHANNEL_MAX][LEDC_SPEED_MODE_MAX]; - static ledc_timer_config_t *timerList[LEDC_TIMER_MAX][LEDC_SPEED_MODE_MAX]; - - ledc_channel_config_t *channel=NULL; - ledc_timer_config_t *timer; - - LedC(uint8_t pin, uint16_t freq); - - public: - int getPin(){return(channel?channel->gpio_num:-1);} // returns the pin number - - operator bool(){ // override boolean operator to return true/false if creation succeeded/failed - return(channel); - } - -}; - -///////////////////////////////////// - -class LedPin : public LedC { - - public: - LedPin(uint8_t pin, float level=0, uint16_t freq=DEFAULT_PWM_FREQ); // assigns pin to be output of one of 16 PWM channels initial level and frequency - void set(float level); // sets the PWM duty to level (0-100) - - static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B -}; - - - -//////////////////////////////// -// ServoPin // -//////////////////////////////// - -class ServoPin : public LedC { - uint16_t minMicros; - uint16_t maxMicros; - double minDegrees; - double microsPerDegree; - - public: - ServoPin(uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees); - ServoPin(uint8_t pin, double initDegrees=0) : ServoPin(pin,initDegrees,1000,2000,-90,90) {}; - - void set(double degrees); // sets the Servo to degrees, where degrees is bounded by [minDegrees,maxDegrees] -}; diff --git a/src/extras/RFControl.h b/src/extras/RFControl.h index 34cceb2..bfbcaea 100644 --- a/src/extras/RFControl.h +++ b/src/extras/RFControl.h @@ -24,53 +24,6 @@ * SOFTWARE. * ********************************************************************************/ + +#include "../src/extras/RFControl.h" -//////////////////////////////////// -// RF Control Module // -//////////////////////////////////// - -#pragma once - -#include -#include -#include "driver/rmt.h" -#include - -using std::vector; - -class RFControl { - friend class Pixel; - - private: - rmt_config_t *config=NULL; - vector data; - boolean lowWord=true; - boolean refClock; - static uint8_t nChannels; - - RFControl(uint8_t pin, boolean refClock, boolean installDriver); // private constructor (only used by Pixel class) - - public: - RFControl(uint8_t pin, boolean refClock=true):RFControl(pin,refClock,true){}; // public constructor to create transmitter on pin, using 1-MHz Ref Tick clock or 80-MHz APB clock - - void start(uint32_t *data, int nData, uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from specified data pointer, repeated for numCycles, where each tick in pulse is tickTime microseconds long - void start(uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from internal data structure, repeated for numCycles, where each tick in pulse is tickTime microseconds long - - void clear(); // clears transmitter memory - void add(uint32_t onTime, uint32_t offTime); // adds pulse of onTime ticks HIGH followed by offTime ticks LOW - void phase(uint32_t nTicks, uint8_t phase); // adds either a HIGH phase or LOW phase lasting numTicks ticks - void enableCarrier(uint32_t freq, float duty=0.5); // enables carrier wave if freq>0, else disables carrier wave; duty is a fraction from 0-1 - void disableCarrier(){enableCarrier(0);} // disables carrier wave - - int getPin(){return(config?config->gpio_num:-1);} // returns the pin number, or -1 if no channel defined - rmt_channel_t getChannel(){return(config?config->channel:RMT_CHANNEL_0);} // returns channel, or channel_0 is no channel defined - - operator bool(){ // override boolean operator to return true/false if creation succeeded/failed - return(config); - } -}; - -// Helper macro for creating your own storage of uint32_t data array elements - used with first variation of start() above - -#define RF_PULSE(highTicks,lowTicks) (1 << 15 | uint32_t(highTicks) | uint32_t(lowTicks) << 16) - diff --git a/src/src.ino b/src/src.ino index a0ba37e..892c050 100644 --- a/src/src.ino +++ b/src/src.ino @@ -5,6 +5,10 @@ #include "HomeSpan.h" #include "FeatherPins.h" #include "extras/Pixel.h" +#include "extras/RFControl.h" +#include "extras/Blinker.h" +#include "extras/PwmPin.h" + #define STRING_t const char * // WORK-AROUND diff --git a/src/extras/Blinker.cpp b/src/src/extras/Blinker.cpp similarity index 100% rename from src/extras/Blinker.cpp rename to src/src/extras/Blinker.cpp diff --git a/src/src/extras/Blinker.h b/src/src/extras/Blinker.h new file mode 100644 index 0000000..633bc19 --- /dev/null +++ b/src/src/extras/Blinker.h @@ -0,0 +1,128 @@ +/********************************************************************************* + * MIT License + * + * Copyright (c) 2020-2022 Gregg E. Berman + * + * https://github.com/HomeSpan/HomeSpan + * + * 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 notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + ********************************************************************************/ + +#pragma once + +#include +#include + +//////////////////////////////// +// Blinkable Interface // +//////////////////////////////// + +class Blinkable { + public: + + virtual void on()=0; + virtual void off()=0; + virtual int getPin()=0; +}; + +//////////////////////////////// +// Blinker // +//////////////////////////////// + +class Blinker { + + TaskHandle_t blinkHandle = NULL; + Blinkable *led; + + int nBlinks; + int onTime; + int offTime; + int delayTime; + + unsigned long pauseDuration; + unsigned long pauseTime; + boolean isPaused=false; + + static void blinkTask(void *arg); + + public: + + Blinker(Blinkable *led, uint16_t autoOffDuration=0); + +// Creates a generic blinking LED in a separate task thread +// +// led: An initialized LED device that implements the Blinkable Interface +//// +// autoOffDuration: If greater than zero, Blinker will automatically turn off after autoOffDuration (in seconds) has elapsed +// Blinker will resume normal operation upon next call to start(), on(), or off() +// Program must periodically call check() for auto-off functionality to work + + void start(int period, float dutyCycle=0.5); + +// Starts simple ON/OFF blinking. +// +// period: ON/OFF blinking period, in milliseconds +// dutyCycle: Fraction of period that LED is ON (default=50%) + + void start(int period, float dutyCycle, int nBlinks, int delayTime); + +// Starts ON/OFF blinking pattern. +// +// period: ON/OFF blinking period, in milliseconds, used for blinking portion of pattern +// dutyCycle: Fraction of period that LED is ON (default=50%) +// nBlinks: Number of blinks in blinking portion of pattern +// delayTime: delay, in milliseconds, during which LED is off before restarting blinking pattern + + void stop(); + +// Stops current blinking pattern. + + void on(); + +// Stops current blinking pattern and turns on LED + + void off(); + +// Stops current blinking pattern and turns off LED + + void check(); + +// Optional check to see if LED output should be paused (check is bypassed if pauseDuration=0) + + int getPin(); + +// Returns pin number of connected LED + +}; + +//////////////////////////////// +// GenericLED // +//////////////////////////////// + +class GenericLED : public Blinkable { + int pin; + + public: + + GenericLED(int pin) : pin{pin} {pinMode(pin,OUTPUT);digitalWrite(pin,0);} + void on() {digitalWrite(pin,HIGH);} + void off() {digitalWrite(pin,LOW);} + int getPin() {return(pin);} +}; diff --git a/src/extras/Pixel.cpp b/src/src/extras/Pixel.cpp similarity index 100% rename from src/extras/Pixel.cpp rename to src/src/extras/Pixel.cpp diff --git a/src/src/extras/Pixel.h b/src/src/extras/Pixel.h new file mode 100644 index 0000000..e781129 --- /dev/null +++ b/src/src/extras/Pixel.h @@ -0,0 +1,259 @@ +/********************************************************************************* + * MIT License + * + * Copyright (c) 2020-2022 Gregg E. Berman + * + * https://github.com/HomeSpan/HomeSpan + * + * 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 notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + ********************************************************************************/ + +//////////////////////////////////////////// +// Addressable LEDs // +//////////////////////////////////////////// + +#pragma once + +#include "RFControl.h" +#include "PwmPin.h" +#include "Blinker.h" + +//////////////////////////////////////////// +// Single-Wire RGB/RGBW NeoPixels // +//////////////////////////////////////////// + +class Pixel : public Blinkable { + + public: + struct Color { + union{ + struct { + uint8_t white:8; + uint8_t blue:8; + uint8_t red:8; + uint8_t green:8; + }; + uint32_t val; + }; + + Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0){ // returns Color based on provided RGB(W) values where r/g/b/w=[0-255] + this->red=r; + this->green=g; + this->blue=b; + this->white=w; + return(*this); + } + + 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] + float r,g,b; + LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b); + this->red=r*255; + this->green=g*255; + this->blue=b*255; + this->white=w*2.555; + return(*this); + } + + bool operator==(const Color& color){ + return(val==color.val); + } + + bool operator!=(const Color& color){ + return(val!=color.val); + } + + Color operator+(const Color& color){ + Color newColor; + newColor.white=white+color.white; + newColor.blue=blue+color.blue; + newColor.red=red+color.red; + newColor.green=green+color.green; + return(newColor); + } + + Color& operator+=(const Color& color){ + white+=color.white; + red+=color.red; + blue+=color.blue; + green+=color.green; + return(*this); + } + + Color operator-(const Color& color){ + Color newColor; + newColor.white=white-color.white; + newColor.blue=blue-color.blue; + newColor.red=red-color.red; + newColor.green=green-color.green; + return(newColor); + } + + Color& operator-=(const Color& color){ + white-=color.white; + red-=color.red; + blue-=color.blue; + green-=color.green; + return(*this); + } + + }; // Color + + private: + struct pixel_status_t { + int nPixels; + Color *color; + int iBit; + int iMem; + boolean started; + Pixel *px; + boolean multiColor; + }; + + RFControl *rf; // Pixel utilizes RFControl + uint32_t pattern[2]; // storage for zero-bit and one-bit pulses + 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 + uint32_t lastBit; // 0=RGBW; 8=RGB + Color onColor; // color used for on() command + + const int memSize=sizeof(RMTMEM.chan[0].data32)/4; // determine size (in pulses) of one channel + + static void loadData(void *arg); // interrupt handler + volatile static pixel_status_t status; // storage for volatile information modified in interupt handler + + public: + 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) + 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 + + static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0){return(Color().RGB(r,g,b,w));} // an alternative method for returning an RGB Color + static Color HSV(float h, float s, float v, double w=0){return(Color().HSV(h,s,v,w));} // an alternative method for returning an HSV Color + + int getPin(){return(rf->getPin());} // returns pixel pin if valid, else returns -1 + 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); + } + + void on() {set(onColor);} + void off() {set(RGB(0,0,0,0));} + Pixel *setOnColor(Color c){onColor=c;return(this);} +}; + +//////////////////////////////////////////// +// Two-Wire RGB DotStars // +//////////////////////////////////////////// + +class Dot { + + public: + struct Color { + union{ + struct { + uint8_t red:8; + uint8_t green:8; + uint8_t blue:8; + uint8_t drive:5; + uint8_t flags:3; + }; + uint32_t val; + }; + + Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31){ // returns Color based on provided RGB values where r/g/b=[0-255] and current-limiting drive level=[0,31] + this->red=r; + this->green=g; + this->blue=b; + this->drive=driveLevel; + this->flags=7; + return(*this); + } + + Color HSV(float h, float s, float v, double drivePercent=100){ // returns Color based on provided HSV values where h=[0,360], s/v=[0,100], and current-limiting drive percent=[0,100] + float r,g,b; + LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b); + this->red=r*255; + this->green=g*255; + this->blue=b*255; + this->drive=drivePercent*0.315; + this->flags=7; + return(*this); + } + + bool operator==(const Color& color){ + return(val==color.val); + } + + bool operator!=(const Color& color){ + return(val!=color.val); + } + + Color operator+(const Color& color){ + Color newColor; + newColor.blue=blue+color.blue; + newColor.red=red+color.red; + newColor.green=green+color.green; + return(newColor); + } + + Color& operator+=(const Color& color){ + red+=color.red; + blue+=color.blue; + green+=color.green; + return(*this); + } + + Color operator-(const Color& color){ + Color newColor; + newColor.blue=blue-color.blue; + newColor.red=red-color.red; + newColor.green=green-color.green; + return(newColor); + } + + Color& operator-=(const Color& color){ + red-=color.red; + blue-=color.blue; + green-=color.green; + return(*this); + } + + }; + + private: + uint32_t dataMask; + uint32_t clockMask; + volatile uint32_t *dataSetReg; + volatile uint32_t *dataClearReg; + volatile uint32_t *clockSetReg; + volatile uint32_t *clockClearReg; + + public: + 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) + 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 + + static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31){return(Color().RGB(r,g,b,driveLevel));} // an alternative method for returning an RGB Color + static Color HSV(float h, float s, float v, double drivePercent=100){return(Color().HSV(h,s,v,drivePercent));} // an alternative method for returning an HSV Color + +}; + +//////////////////////////////////////////// diff --git a/src/extras/PwmPin.cpp b/src/src/extras/PwmPin.cpp similarity index 100% rename from src/extras/PwmPin.cpp rename to src/src/extras/PwmPin.cpp diff --git a/src/src/extras/PwmPin.h b/src/src/extras/PwmPin.h new file mode 100644 index 0000000..d9506ec --- /dev/null +++ b/src/src/extras/PwmPin.h @@ -0,0 +1,101 @@ +/********************************************************************************* + * MIT License + * + * Copyright (c) 2020-2022 Gregg E. Berman + * + * https://github.com/HomeSpan/HomeSpan + * + * 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 notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + ********************************************************************************/ + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ----- PWM Pin Control ----- +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Wrappers around the ESP-IDF ledc library to control PWM-based devices: +// +// LedPin(pin) - controls a Dimmable LED on specified pin with frequency=5000 Hz +// - use set(level) to set brightness from 0-100% +// +// ServoPin(pin) - controls a Servo Motor on specified pin with frequency=50 Hz +// - use set(degrees) to set position to degrees +// +// +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include "Blinker.h" + +#define DEFAULT_PWM_FREQ 5000 + +///////////////////////////////////// + +class LedC { + + protected: + static ledc_channel_config_t *channelList[LEDC_CHANNEL_MAX][LEDC_SPEED_MODE_MAX]; + static ledc_timer_config_t *timerList[LEDC_TIMER_MAX][LEDC_SPEED_MODE_MAX]; + + ledc_channel_config_t *channel=NULL; + ledc_timer_config_t *timer; + + LedC(uint8_t pin, uint16_t freq); + + public: + int getPin(){return(channel?channel->gpio_num:-1);} // returns the pin number + + operator bool(){ // override boolean operator to return true/false if creation succeeded/failed + return(channel); + } + +}; + +///////////////////////////////////// + +class LedPin : public LedC { + + public: + LedPin(uint8_t pin, float level=0, uint16_t freq=DEFAULT_PWM_FREQ); // assigns pin to be output of one of 16 PWM channels initial level and frequency + void set(float level); // sets the PWM duty to level (0-100) + + static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B +}; + + + +//////////////////////////////// +// ServoPin // +//////////////////////////////// + +class ServoPin : public LedC { + uint16_t minMicros; + uint16_t maxMicros; + double minDegrees; + double microsPerDegree; + + public: + ServoPin(uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees); + ServoPin(uint8_t pin, double initDegrees=0) : ServoPin(pin,initDegrees,1000,2000,-90,90) {}; + + void set(double degrees); // sets the Servo to degrees, where degrees is bounded by [minDegrees,maxDegrees] +}; diff --git a/src/extras/RFControl.cpp b/src/src/extras/RFControl.cpp similarity index 100% rename from src/extras/RFControl.cpp rename to src/src/extras/RFControl.cpp diff --git a/src/src/extras/RFControl.h b/src/src/extras/RFControl.h new file mode 100644 index 0000000..34cceb2 --- /dev/null +++ b/src/src/extras/RFControl.h @@ -0,0 +1,76 @@ +/********************************************************************************* + * MIT License + * + * Copyright (c) 2020-2022 Gregg E. Berman + * + * https://github.com/HomeSpan/HomeSpan + * + * 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 notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + ********************************************************************************/ + +//////////////////////////////////// +// RF Control Module // +//////////////////////////////////// + +#pragma once + +#include +#include +#include "driver/rmt.h" +#include + +using std::vector; + +class RFControl { + friend class Pixel; + + private: + rmt_config_t *config=NULL; + vector data; + boolean lowWord=true; + boolean refClock; + static uint8_t nChannels; + + RFControl(uint8_t pin, boolean refClock, boolean installDriver); // private constructor (only used by Pixel class) + + public: + RFControl(uint8_t pin, boolean refClock=true):RFControl(pin,refClock,true){}; // public constructor to create transmitter on pin, using 1-MHz Ref Tick clock or 80-MHz APB clock + + void start(uint32_t *data, int nData, uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from specified data pointer, repeated for numCycles, where each tick in pulse is tickTime microseconds long + void start(uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from internal data structure, repeated for numCycles, where each tick in pulse is tickTime microseconds long + + void clear(); // clears transmitter memory + void add(uint32_t onTime, uint32_t offTime); // adds pulse of onTime ticks HIGH followed by offTime ticks LOW + void phase(uint32_t nTicks, uint8_t phase); // adds either a HIGH phase or LOW phase lasting numTicks ticks + void enableCarrier(uint32_t freq, float duty=0.5); // enables carrier wave if freq>0, else disables carrier wave; duty is a fraction from 0-1 + void disableCarrier(){enableCarrier(0);} // disables carrier wave + + int getPin(){return(config?config->gpio_num:-1);} // returns the pin number, or -1 if no channel defined + rmt_channel_t getChannel(){return(config?config->channel:RMT_CHANNEL_0);} // returns channel, or channel_0 is no channel defined + + operator bool(){ // override boolean operator to return true/false if creation succeeded/failed + return(config); + } +}; + +// Helper macro for creating your own storage of uint32_t data array elements - used with first variation of start() above + +#define RF_PULSE(highTicks,lowTicks) (1 << 15 | uint32_t(highTicks) | uint32_t(lowTicks) << 16) + diff --git a/src/extras/extras.ino b/src/src/extras/extras.ino similarity index 100% rename from src/extras/extras.ino rename to src/src/extras/extras.ino