Modified folder structure for "extras"
This allows the "src.ino" test file to once again properly compile without requiring modifications to any existing HomeSpan sketches. This was needed to ensure src.ino can find object code in "extras", which is now required to use the new statusDevice() method. Since the Arduino IDE only copies files that are in "src" folders, "extras" needed to be moved to "src/extras". For backwards compatibility with all other sketches, the "extras" directory now contains stubs for the ".h" include files.
This commit is contained in:
parent
66160e7c6c
commit
dbe4c268f4
|
|
@ -25,104 +25,6 @@
|
|||
*
|
||||
********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "../src/extras/Blinker.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <driver/timer.h>
|
||||
|
||||
////////////////////////////////
|
||||
// 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);}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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 <Arduino.h>
|
||||
#include <driver/ledc.h>
|
||||
#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]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,52 +25,5 @@
|
|||
*
|
||||
********************************************************************************/
|
||||
|
||||
////////////////////////////////////
|
||||
// RF Control Module //
|
||||
////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <soc/rmt_reg.h>
|
||||
#include "driver/rmt.h"
|
||||
#include <vector>
|
||||
|
||||
using std::vector;
|
||||
|
||||
class RFControl {
|
||||
friend class Pixel;
|
||||
|
||||
private:
|
||||
rmt_config_t *config=NULL;
|
||||
vector<uint32_t> 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)
|
||||
#include "../src/extras/RFControl.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <Arduino.h>
|
||||
#include <driver/timer.h>
|
||||
|
||||
////////////////////////////////
|
||||
// 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);}
|
||||
};
|
||||
|
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
|
@ -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 <Arduino.h>
|
||||
#include <driver/ledc.h>
|
||||
#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]
|
||||
};
|
||||
|
|
@ -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 <Arduino.h>
|
||||
#include <soc/rmt_reg.h>
|
||||
#include "driver/rmt.h"
|
||||
#include <vector>
|
||||
|
||||
using std::vector;
|
||||
|
||||
class RFControl {
|
||||
friend class Pixel;
|
||||
|
||||
private:
|
||||
rmt_config_t *config=NULL;
|
||||
vector<uint32_t> 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)
|
||||
|
||||
Loading…
Reference in New Issue