started development of Blinkable Interface to allow generic LED to be used with Blinker
This commit is contained in:
parent
c286875640
commit
fc76db092d
|
|
@ -637,7 +637,9 @@ int HAPClient::postPairSetupURL(){
|
|||
mdns_service_txt_item_set("_hap","_tcp","sf","0"); // broadcast new status
|
||||
|
||||
LOG1("\n*** ACCESSORY PAIRED! ***\n");
|
||||
homeSpan.statusLED.on();
|
||||
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->on();
|
||||
|
||||
if(homeSpan.pairCallback) // if set, invoke user-defined Pairing Callback to indicate device has been paired
|
||||
homeSpan.pairCallback(true);
|
||||
|
|
@ -1636,7 +1638,8 @@ void HAPClient::removeController(uint8_t *id){
|
|||
removeControllers();
|
||||
LOG1("That was last Admin Controller! Removing any remaining Regular Controllers and unpairing Accessory\n");
|
||||
mdns_service_txt_item_set("_hap","_tcp","sf","1"); // set Status Flag = 1 (Table 6-8)
|
||||
homeSpan.statusLED.start(LED_PAIRING_NEEDED);
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_PAIRING_NEEDED);
|
||||
if(homeSpan.pairCallback) // if set, invoke user-defined Pairing Callback to indicate device has been paired
|
||||
homeSpan.pairCallback(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
|
|||
|
||||
esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); // required to avoid watchdog timeout messages from ESP32-C3
|
||||
|
||||
statusLED.init(statusPin,0,autoOffLED);
|
||||
|
||||
if(requestedMaxCon<maxConnections) // if specific request for max connections is less than computed max connections
|
||||
maxConnections=requestedMaxCon; // over-ride max connections with requested value
|
||||
|
||||
|
|
@ -96,8 +94,8 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
|
|||
Serial.print("Message Logs: Level ");
|
||||
Serial.print(logLevel);
|
||||
Serial.print("\nStatus LED: Pin ");
|
||||
if(statusPin>=0){
|
||||
Serial.print(statusPin);
|
||||
if(getStatusPin()>=0){
|
||||
Serial.print(getStatusPin());
|
||||
if(autoOffLED>0)
|
||||
Serial.printf(" (Auto Off=%d sec)",autoOffLED);
|
||||
}
|
||||
|
|
@ -189,10 +187,11 @@ void Span::pollTask() {
|
|||
processSerialCommand("A");
|
||||
} else {
|
||||
Serial.print("YOU MAY CONFIGURE BY TYPING 'W <RETURN>'.\n\n");
|
||||
statusLED.start(LED_WIFI_NEEDED);
|
||||
if(statusLED)
|
||||
statusLED->start(LED_WIFI_NEEDED);
|
||||
}
|
||||
} else {
|
||||
homeSpan.statusLED.start(LED_WIFI_CONNECTING);
|
||||
} else if(statusLED) {
|
||||
statusLED->start(LED_WIFI_CONNECTING);
|
||||
}
|
||||
|
||||
if(controlButton)
|
||||
|
|
@ -290,12 +289,12 @@ void Span::pollTask() {
|
|||
if(spanOTA.enabled)
|
||||
ArduinoOTA.handle();
|
||||
|
||||
if(controlButton && controlButton->primed()){
|
||||
statusLED.start(LED_ALERT);
|
||||
}
|
||||
if(controlButton && controlButton->primed() && statusLED)
|
||||
statusLED->start(LED_ALERT);
|
||||
|
||||
if(controlButton && controlButton->triggered(3000,10000)){
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
if(controlButton->type()==PushButton::LONG){
|
||||
controlButton->wait();
|
||||
processSerialCommand("F"); // FACTORY RESET
|
||||
|
|
@ -304,7 +303,8 @@ void Span::pollTask() {
|
|||
}
|
||||
}
|
||||
|
||||
statusLED.check();
|
||||
if(statusLED)
|
||||
statusLED->check();
|
||||
|
||||
} // poll
|
||||
|
||||
|
|
@ -323,11 +323,16 @@ int Span::getFreeSlot(){
|
|||
//////////////////////////////////////
|
||||
|
||||
void Span::commandMode(){
|
||||
|
||||
if(!statusLED){
|
||||
Serial.print("*** ERROR: CAN'T ENTER COMMAND MODE WITHOUT A DEFINED STATUS LED***\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("*** ENTERING COMMAND MODE ***\n\n");
|
||||
int mode=1;
|
||||
boolean done=false;
|
||||
statusLED.start(500,0.3,mode,1000);
|
||||
statusLED->start(500,0.3,mode,1000);
|
||||
|
||||
unsigned long alarmTime=millis()+comModeLife;
|
||||
|
||||
|
|
@ -338,7 +343,7 @@ void Span::commandMode(){
|
|||
Serial.print(" seconds).\n\n");
|
||||
mode=1;
|
||||
done=true;
|
||||
statusLED.start(LED_ALERT);
|
||||
statusLED->start(LED_ALERT);
|
||||
delay(2000);
|
||||
} else
|
||||
if(controlButton->triggered(10,3000)){
|
||||
|
|
@ -346,14 +351,14 @@ void Span::commandMode(){
|
|||
mode++;
|
||||
if(mode==6)
|
||||
mode=1;
|
||||
statusLED.start(500,0.3,mode,1000);
|
||||
statusLED->start(500,0.3,mode,1000);
|
||||
} else {
|
||||
done=true;
|
||||
}
|
||||
} // button press
|
||||
} // while
|
||||
|
||||
statusLED.start(LED_ALERT);
|
||||
statusLED->start(LED_ALERT);
|
||||
controlButton->wait();
|
||||
|
||||
switch(mode){
|
||||
|
|
@ -361,12 +366,12 @@ void Span::commandMode(){
|
|||
case 1:
|
||||
Serial.print("*** NO ACTION\n\n");
|
||||
if(strlen(network.wifiData.ssid)==0)
|
||||
statusLED.start(LED_WIFI_NEEDED);
|
||||
statusLED->start(LED_WIFI_NEEDED);
|
||||
else
|
||||
if(!HAPClient::nAdminControllers())
|
||||
statusLED.start(LED_PAIRING_NEEDED);
|
||||
statusLED->start(LED_PAIRING_NEEDED);
|
||||
else
|
||||
statusLED.on();
|
||||
statusLED->on();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
|
@ -402,7 +407,8 @@ void Span::checkConnect(){
|
|||
connected++;
|
||||
waitTime=60000;
|
||||
alarmConnect=0;
|
||||
homeSpan.statusLED.start(LED_WIFI_CONNECTING);
|
||||
if(statusLED)
|
||||
statusLED->start(LED_WIFI_CONNECTING);
|
||||
}
|
||||
|
||||
if(WiFi.status()!=WL_CONNECTED){
|
||||
|
|
@ -429,10 +435,12 @@ void Span::checkConnect(){
|
|||
return;
|
||||
}
|
||||
|
||||
if(!HAPClient::nAdminControllers())
|
||||
statusLED.start(LED_PAIRING_NEEDED);
|
||||
else
|
||||
statusLED.on();
|
||||
if(statusLED){
|
||||
if(!HAPClient::nAdminControllers())
|
||||
statusLED->start(LED_PAIRING_NEEDED);
|
||||
else
|
||||
statusLED->on();
|
||||
}
|
||||
|
||||
connected++;
|
||||
|
||||
|
|
@ -756,11 +764,13 @@ void Span::processSerialCommand(const char *c){
|
|||
|
||||
Serial.print("\nDEVICE NOT YET PAIRED -- PLEASE PAIR WITH HOMEKIT APP\n\n");
|
||||
mdns_service_txt_item_set("_hap","_tcp","sf","1"); // set Status Flag = 1 (Table 6-8)
|
||||
|
||||
if(strlen(network.wifiData.ssid)==0)
|
||||
statusLED.start(LED_WIFI_NEEDED);
|
||||
else
|
||||
statusLED.start(LED_PAIRING_NEEDED);
|
||||
|
||||
if(statusLED){
|
||||
if(strlen(network.wifiData.ssid)==0)
|
||||
statusLED->start(LED_WIFI_NEEDED);
|
||||
else
|
||||
statusLED->start(LED_PAIRING_NEEDED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -777,7 +787,8 @@ void Span::processSerialCommand(const char *c){
|
|||
nvs_set_blob(wifiNVS,"WIFIDATA",&network.wifiData,sizeof(network.wifiData)); // update data
|
||||
nvs_commit(wifiNVS); // commit to NVS
|
||||
Serial.print("\n*** WiFi Credentials SAVED! Re-starting ***\n\n");
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
delay(1000);
|
||||
ESP.restart();
|
||||
}
|
||||
|
|
@ -810,7 +821,8 @@ void Span::processSerialCommand(const char *c){
|
|||
}
|
||||
|
||||
Serial.print("\n*** Re-starting ***\n\n");
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
delay(1000);
|
||||
ESP.restart(); // re-start device
|
||||
}
|
||||
|
|
@ -818,7 +830,8 @@ void Span::processSerialCommand(const char *c){
|
|||
|
||||
case 'X': {
|
||||
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
nvs_erase_all(wifiNVS);
|
||||
nvs_commit(wifiNVS);
|
||||
Serial.print("\n*** WiFi Credentials ERASED! Re-starting...\n\n");
|
||||
|
|
@ -837,7 +850,8 @@ void Span::processSerialCommand(const char *c){
|
|||
|
||||
case 'H': {
|
||||
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
nvs_erase_all(HAPClient::hapNVS);
|
||||
nvs_commit(HAPClient::hapNVS);
|
||||
Serial.print("\n*** HomeSpan Device ID and Pairing Data DELETED! Restarting...\n\n");
|
||||
|
|
@ -848,7 +862,8 @@ void Span::processSerialCommand(const char *c){
|
|||
|
||||
case 'R': {
|
||||
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
Serial.print("\n*** Restarting...\n\n");
|
||||
delay(1000);
|
||||
ESP.restart();
|
||||
|
|
@ -857,7 +872,8 @@ void Span::processSerialCommand(const char *c){
|
|||
|
||||
case 'F': {
|
||||
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
nvs_erase_all(HAPClient::hapNVS);
|
||||
nvs_commit(HAPClient::hapNVS);
|
||||
nvs_erase_all(wifiNVS);
|
||||
|
|
@ -874,7 +890,8 @@ void Span::processSerialCommand(const char *c){
|
|||
|
||||
case 'E': {
|
||||
|
||||
statusLED.off();
|
||||
if(statusLED)
|
||||
statusLED->off();
|
||||
nvs_flash_erase();
|
||||
Serial.print("\n*** ALL DATA ERASED! Restarting...\n\n");
|
||||
delay(1000);
|
||||
|
|
@ -2098,7 +2115,8 @@ void SpanOTA::start(){
|
|||
Serial.printf("\n*** Current Partition: %s\n*** New Partition: %s\n*** OTA Starting..",
|
||||
esp_ota_get_running_partition()->label,esp_ota_get_next_update_partition(NULL)->label);
|
||||
otaPercent=0;
|
||||
homeSpan.statusLED.start(LED_OTA_STARTED);
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_OTA_STARTED);
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
|
@ -2107,7 +2125,8 @@ void SpanOTA::end(){
|
|||
nvs_set_u8(homeSpan.otaNVS,"OTA_REQUIRED",safeLoad);
|
||||
nvs_commit(homeSpan.otaNVS);
|
||||
Serial.printf(" DONE! Rebooting...\n");
|
||||
homeSpan.statusLED.off();
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->off();
|
||||
delay(100); // make sure commit it finished before reboot
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <nvs.h>
|
||||
#include <ArduinoOTA.h>
|
||||
|
||||
#include "extras/Blinker.h"
|
||||
#include "Settings.h"
|
||||
#include "Utils.h"
|
||||
#include "Network.h"
|
||||
|
|
@ -189,7 +190,6 @@ class Span{
|
|||
unsigned long alarmConnect=0; // time after which WiFi connection attempt should be tried again
|
||||
|
||||
const char *defaultSetupCode=DEFAULT_SETUP_CODE; // Setup Code used for pairing
|
||||
int statusPin=DEFAULT_STATUS_PIN; // pin for Status LED
|
||||
uint16_t autoOffLED=0; // automatic turn-off duration (in seconds) for Status LED
|
||||
uint8_t logLevel=DEFAULT_LOG_LEVEL; // level for writing out log messages to serial monitor
|
||||
uint8_t maxConnections=CONFIG_LWIP_MAX_SOCKETS-2; // maximum number of allowed simultaneous HAP connections
|
||||
|
|
@ -203,7 +203,7 @@ class Span{
|
|||
void (*apFunction)()=NULL; // optional function to invoke when starting Access Point
|
||||
|
||||
WiFiServer *hapServer; // pointer to the HAP Server connection
|
||||
Blinker statusLED; // indicates HomeSpan status
|
||||
Blinker *statusLED = NULL; // indicates HomeSpan status
|
||||
PushButton *controlButton = NULL; // controls HomeSpan configuration and resets
|
||||
Network network; // configures WiFi and Setup Code via either serial monitor or temporary Access Point
|
||||
SpanWebLog webLog; // optional web status/log
|
||||
|
|
@ -254,10 +254,12 @@ class Span{
|
|||
boolean updateDatabase(boolean updateMDNS=true); // updates HAP Configuration Number and Loop vector; if updateMDNS=true and config number has changed, re-broadcasts MDNS 'c#' record; returns true if config number changed
|
||||
boolean deleteAccessory(uint32_t aid); // deletes Accessory with matching aid; returns true if found, else returns false
|
||||
|
||||
void setControlPin(uint8_t pin){controlButton=new PushButton(pin);} // sets Control Pin
|
||||
void setStatusPin(uint8_t pin){statusPin=pin;} // sets Status Pin
|
||||
void setControlPin(uint8_t pin){controlButton=new PushButton(pin);} // sets Control Pin
|
||||
void setStatusPin(uint8_t pin){statusLED=new Blinker(new LED(pin),0,autoOffLED);} // sets Status Pin
|
||||
// void setStatusPin(Blinkable *led){statusLED=new Blinker(led,0,autoOffLED);} // sets Status Blinkable LED
|
||||
|
||||
void setStatusAutoOff(uint16_t duration){autoOffLED=duration;} // sets Status LED auto off (seconds)
|
||||
int getStatusPin(){return(statusPin);} // get Status Pin
|
||||
int getStatusPin(){return(statusLED?statusLED->getPin():-1);} // get Status Pin (returns -1 if undefined)
|
||||
int getControlPin(){return(controlButton?controlButton->getPin():-1);} // get Control Pin (returns -1 if undefined)
|
||||
void setApSSID(const char *ssid){network.apSSID=ssid;} // sets Access Point SSID
|
||||
void setApPassword(const char *pwd){network.apPassword=pwd;} // sets Access Point Password
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
#include "Network.h"
|
||||
#include "HomeSpan.h"
|
||||
#include "Utils.h"
|
||||
#include "extras/Blinker.h"
|
||||
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
|
|
@ -116,7 +118,8 @@ void Network::apConfigure(){
|
|||
Serial.print(apPassword);
|
||||
Serial.print("\n");
|
||||
|
||||
homeSpan.statusLED.start(LED_AP_STARTED);
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_AP_STARTED);
|
||||
|
||||
Serial.print("\nScanning for Networks...\n\n");
|
||||
|
||||
|
|
@ -154,10 +157,12 @@ void Network::apConfigure(){
|
|||
|
||||
if(homeSpan.controlButton && homeSpan.controlButton->triggered(9999,3000)){
|
||||
Serial.print("\n*** Access Point Terminated.");
|
||||
homeSpan.statusLED.start(LED_ALERT);
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_ALERT);
|
||||
homeSpan.controlButton->wait();
|
||||
Serial.print(" Restarting... \n\n");
|
||||
homeSpan.statusLED.off();
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->off();
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
|
|
@ -176,9 +181,11 @@ void Network::apConfigure(){
|
|||
Serial.print("\n*** Access Point: Configuration Canceled.");
|
||||
}
|
||||
Serial.print(" Restarting...\n\n");
|
||||
homeSpan.statusLED.start(LED_ALERT);
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_ALERT);
|
||||
delay(1000);
|
||||
homeSpan.statusLED.off();
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->off();
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
|
|
@ -273,7 +280,8 @@ void Network::processRequest(char *body, char *formData){
|
|||
getFormValue(formData,"network",wifiData.ssid,MAX_SSID);
|
||||
getFormValue(formData,"pwd",wifiData.pwd,MAX_PWD);
|
||||
|
||||
homeSpan.statusLED.start(LED_WIFI_CONNECTING);
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_WIFI_CONNECTING);
|
||||
|
||||
responseBody+="<meta http-equiv = \"refresh\" content = \"" + String(waitTime) + "; url = /wifi-status\" />"
|
||||
"<p>Initiating WiFi connection to:</p><p><b>" + String(wifiData.ssid) + "</p>";
|
||||
|
|
@ -320,7 +328,8 @@ void Network::processRequest(char *body, char *formData){
|
|||
|
||||
} else {
|
||||
|
||||
homeSpan.statusLED.start(LED_AP_CONNECTED); // slow double-blink
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_AP_CONNECTED); // slow double-blink
|
||||
|
||||
responseBody+="<p>SUCCESS! Connected to:</p><p><b>" + String(wifiData.ssid) + "</b></p>";
|
||||
responseBody+="<p>You may enter new 8-digit Setup Code below, or leave blank to retain existing code.</p>";
|
||||
|
|
@ -340,7 +349,8 @@ void Network::processRequest(char *body, char *formData){
|
|||
|
||||
LOG1("In Landing Page...\n");
|
||||
|
||||
homeSpan.statusLED.start(LED_AP_CONNECTED);
|
||||
if(homeSpan.statusLED)
|
||||
homeSpan.statusLED->start(LED_AP_CONNECTED);
|
||||
waitTime=2;
|
||||
|
||||
responseBody+="<p>Welcome to HomeSpan! This page allows you to configure the above HomeSpan device to connect to your WiFi network.</p>"
|
||||
|
|
|
|||
|
|
@ -71,8 +71,6 @@
|
|||
|
||||
#define DEFAULT_QR_ID "HSPN" // change with homeSpan.setQRID(qrID);
|
||||
|
||||
#define DEFAULT_STATUS_PIN -1 // change with homeSpan.setStatusPin(pin)
|
||||
|
||||
#define DEFAULT_AP_SSID "HomeSpan-Setup" // change with homeSpan.setApSSID(ssid)
|
||||
#define DEFAULT_AP_PASSWORD "homespan" // change with homeSpan.setApPassword(pwd)
|
||||
#define DEFAULT_OTA_PASSWORD "homespan-ota" // change with 'O' command
|
||||
|
|
|
|||
322
src/Utils.cpp
322
src/Utils.cpp
|
|
@ -227,178 +227,150 @@ void PushButton::reset(){
|
|||
touch_value_t PushButton::threshold=0;
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
// Blinker //
|
||||
////////////////////////////////
|
||||
|
||||
Blinker::Blinker(){
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
Blinker::Blinker(int pin, int timerNum, uint16_t autoOffDuration){
|
||||
init(pin, timerNum, autoOffDuration);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::init(int pin, int timerNum, uint16_t autoOffDuration){
|
||||
|
||||
this->pin=pin;
|
||||
if(pin<0)
|
||||
return;
|
||||
|
||||
pinMode(pin,OUTPUT);
|
||||
digitalWrite(pin,0);
|
||||
|
||||
pauseDuration=autoOffDuration*1000;
|
||||
|
||||
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP>1 // ESP32 and ESP32-S2 contains two timers per timer group
|
||||
group=((timerNum/2)%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
||||
idx=(timerNum%2==0)?TIMER_0:TIMER_1; // ESP32-C3 only contains one timer per timer group
|
||||
#else
|
||||
group=(timerNum%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
||||
idx=TIMER_0;
|
||||
#endif
|
||||
|
||||
timer_config_t conf;
|
||||
conf.alarm_en=TIMER_ALARM_EN;
|
||||
conf.counter_en=TIMER_PAUSE;
|
||||
conf.intr_type=TIMER_INTR_LEVEL;
|
||||
conf.counter_dir=TIMER_COUNT_UP;
|
||||
conf.auto_reload=TIMER_AUTORELOAD_EN;
|
||||
conf.divider=getApbFrequency()/10000; // set divider to yield 10 kHz clock (0.1 ms pulses)
|
||||
|
||||
#ifdef SOC_TIMER_GROUP_SUPPORT_XTAL // set clock to APB (default is XTAL!) if clk_src is defined in conf structure
|
||||
conf.clk_src=TIMER_SRC_CLK_APB;
|
||||
#endif
|
||||
|
||||
timer_init(group,idx,&conf);
|
||||
timer_isr_register(group,idx,Blinker::isrTimer,(void *)this,0,NULL);
|
||||
timer_enable_intr(group,idx);
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::isrTimer(void *arg){
|
||||
|
||||
Blinker *b=(Blinker *)arg;
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) // use new method that is generic to ESP32, S2, and C3
|
||||
timer_group_clr_intr_status_in_isr(b->group,b->idx);
|
||||
#else // use older method that is only for ESP32
|
||||
if(b->group){
|
||||
if(b->idx)
|
||||
TIMERG1.int_clr_timers.t1=1;
|
||||
else
|
||||
TIMERG1.int_clr_timers.t0=1;
|
||||
} else {
|
||||
if(b->idx)
|
||||
TIMERG0.int_clr_timers.t1=1;
|
||||
else
|
||||
TIMERG0.int_clr_timers.t0=1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!digitalRead(b->pin)){
|
||||
digitalWrite(b->pin,1);
|
||||
timer_set_alarm_value(b->group,b->idx,b->onTime);
|
||||
b->count--;
|
||||
} else {
|
||||
digitalWrite(b->pin,0);
|
||||
if(b->count){
|
||||
timer_set_alarm_value(b->group,b->idx,b->offTime);
|
||||
} else {
|
||||
timer_set_alarm_value(b->group,b->idx,b->delayTime);
|
||||
b->count=b->nBlinks;
|
||||
}
|
||||
}
|
||||
|
||||
timer_set_alarm(b->group,b->idx,TIMER_ALARM_EN);
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::start(int period, float dutyCycle){
|
||||
|
||||
start(period, dutyCycle, 1, 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::start(int period, float dutyCycle, int nBlinks, int delayTime){
|
||||
|
||||
if(pin<0)
|
||||
return;
|
||||
|
||||
pauseTime=millis();
|
||||
isPaused=false;
|
||||
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT_OUTPUT); // needed to ensure digitalRead() functions correctly on ESP32-C3; also needed to re-enable after pause()
|
||||
|
||||
period*=10;
|
||||
onTime=dutyCycle*period;
|
||||
offTime=period-onTime;
|
||||
this->delayTime=delayTime*10+offTime;
|
||||
this->nBlinks=nBlinks;
|
||||
count=nBlinks;
|
||||
timer_set_counter_value(group,idx,0);
|
||||
timer_set_alarm_value(group,idx,0);
|
||||
timer_start(group,idx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::stop(){
|
||||
|
||||
if(pin<0)
|
||||
return;
|
||||
|
||||
timer_pause(group,idx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::on(){
|
||||
|
||||
if(pin<0)
|
||||
return;
|
||||
|
||||
pauseTime=millis();
|
||||
isPaused=false;
|
||||
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT_OUTPUT);
|
||||
|
||||
stop();
|
||||
digitalWrite(pin,1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::off(){
|
||||
|
||||
if(pin<0)
|
||||
return;
|
||||
|
||||
pauseTime=millis();
|
||||
isPaused=false;
|
||||
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT_OUTPUT);
|
||||
|
||||
stop();
|
||||
digitalWrite(pin,0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::check(){
|
||||
|
||||
if(pin<0)
|
||||
return;
|
||||
|
||||
if(pauseDuration==0 || isPaused || (millis()-pauseTime)<pauseDuration)
|
||||
return;
|
||||
|
||||
Serial.print("Pausing Status LED\n");
|
||||
isPaused=true;
|
||||
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_DISABLE);
|
||||
}
|
||||
//////////////////////////////////
|
||||
//// Blinker //
|
||||
//////////////////////////////////
|
||||
//
|
||||
//Blinker::Blinker(Blinkable *led, int timerNum, uint16_t autoOffDuration){
|
||||
//
|
||||
// this->led=led;
|
||||
//
|
||||
// pauseDuration=autoOffDuration*1000;
|
||||
//
|
||||
//#if SOC_TIMER_GROUP_TIMERS_PER_GROUP>1 // ESP32 and ESP32-S2 contains two timers per timer group
|
||||
// group=((timerNum/2)%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
||||
// idx=(timerNum%2==0)?TIMER_0:TIMER_1; // ESP32-C3 only contains one timer per timer group
|
||||
//#else
|
||||
// group=(timerNum%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
||||
// idx=TIMER_0;
|
||||
//#endif
|
||||
//
|
||||
// timer_config_t conf;
|
||||
// conf.alarm_en=TIMER_ALARM_EN;
|
||||
// conf.counter_en=TIMER_PAUSE;
|
||||
// conf.intr_type=TIMER_INTR_LEVEL;
|
||||
// conf.counter_dir=TIMER_COUNT_UP;
|
||||
// conf.auto_reload=TIMER_AUTORELOAD_EN;
|
||||
// conf.divider=getApbFrequency()/10000; // set divider to yield 10 kHz clock (0.1 ms pulses)
|
||||
//
|
||||
//#ifdef SOC_TIMER_GROUP_SUPPORT_XTAL // set clock to APB (default is XTAL!) if clk_src is defined in conf structure
|
||||
// conf.clk_src=TIMER_SRC_CLK_APB;
|
||||
//#endif
|
||||
//
|
||||
// timer_init(group,idx,&conf);
|
||||
// timer_isr_register(group,idx,Blinker::isrTimer,(void *)this,0,NULL);
|
||||
// timer_enable_intr(group,idx);
|
||||
//
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//void Blinker::isrTimer(void *arg){
|
||||
//
|
||||
// Blinker *b=(Blinker *)arg;
|
||||
//
|
||||
//#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) // use new method that is generic to ESP32, S2, and C3
|
||||
// timer_group_clr_intr_status_in_isr(b->group,b->idx);
|
||||
//#else // use older method that is only for ESP32
|
||||
// if(b->group){
|
||||
// if(b->idx)
|
||||
// TIMERG1.int_clr_timers.t1=1;
|
||||
// else
|
||||
// TIMERG1.int_clr_timers.t0=1;
|
||||
// } else {
|
||||
// if(b->idx)
|
||||
// TIMERG0.int_clr_timers.t1=1;
|
||||
// else
|
||||
// TIMERG0.int_clr_timers.t0=1;
|
||||
// }
|
||||
//#endif
|
||||
//
|
||||
// if(!(b->led->isOn())){
|
||||
// b->led->on();
|
||||
// timer_set_alarm_value(b->group,b->idx,b->onTime);
|
||||
// b->count--;
|
||||
// } else {
|
||||
// b->led->off();
|
||||
// if(b->count){
|
||||
// timer_set_alarm_value(b->group,b->idx,b->offTime);
|
||||
// } else {
|
||||
// timer_set_alarm_value(b->group,b->idx,b->delayTime);
|
||||
// b->count=b->nBlinks;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// timer_set_alarm(b->group,b->idx,TIMER_ALARM_EN);
|
||||
//
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//void Blinker::start(int period, float dutyCycle){
|
||||
//
|
||||
// start(period, dutyCycle, 1, 0);
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//void Blinker::start(int period, float dutyCycle, int nBlinks, int delayTime){
|
||||
//
|
||||
// pauseTime=millis();
|
||||
// isPaused=false;
|
||||
//
|
||||
// period*=10;
|
||||
// onTime=dutyCycle*period;
|
||||
// offTime=period-onTime;
|
||||
// this->delayTime=delayTime*10+offTime;
|
||||
// this->nBlinks=nBlinks;
|
||||
// count=nBlinks;
|
||||
// timer_set_counter_value(group,idx,0);
|
||||
// timer_set_alarm_value(group,idx,0);
|
||||
// timer_start(group,idx);
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//void Blinker::stop(){
|
||||
//
|
||||
// timer_pause(group,idx);
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//void Blinker::on(){
|
||||
//
|
||||
// pauseTime=millis();
|
||||
// isPaused=false;
|
||||
//
|
||||
// stop();
|
||||
// led->on();
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//void Blinker::off(){
|
||||
//
|
||||
// pauseTime=millis();
|
||||
// isPaused=false;
|
||||
//
|
||||
// stop();
|
||||
// led->off();
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//void Blinker::check(){
|
||||
//
|
||||
// if(pauseDuration==0 || isPaused || (millis()-pauseTime)<pauseDuration)
|
||||
// return;
|
||||
//
|
||||
// Serial.print("Pausing Status LED\n");
|
||||
// isPaused=true;
|
||||
// led->off();
|
||||
//}
|
||||
//
|
||||
////////////////////////////////////////
|
||||
//
|
||||
//int Blinker::getPin(){
|
||||
// return(led->getPin());
|
||||
//}
|
||||
|
|
|
|||
184
src/Utils.h
184
src/Utils.h
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include <driver/timer.h>
|
||||
#include "extras/Blinker.h"
|
||||
|
||||
namespace Utils {
|
||||
|
||||
|
|
@ -37,6 +38,21 @@ String mask(char *c, int n); // simply utility that creates a String fr
|
|||
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Blinkable Interface //
|
||||
////////////////////////////////
|
||||
|
||||
//class Blinkable {
|
||||
// protected:
|
||||
// boolean onState=false;
|
||||
//
|
||||
// public:
|
||||
// virtual void on()=0;
|
||||
// virtual void off()=0;
|
||||
// virtual int getPin()=0;
|
||||
// boolean isOn() {return(onState);}
|
||||
//};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// Creates a temporary buffer that is freed after
|
||||
// going out of scope
|
||||
|
|
@ -182,98 +198,104 @@ class PushButton{
|
|||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
//// Generic_LED //
|
||||
//////////////////////////////////
|
||||
//
|
||||
//class LED : public Blinkable {
|
||||
// int pin;
|
||||
//
|
||||
// public:
|
||||
//
|
||||
// LED(int pin) : pin{pin} {pinMode(pin,OUTPUT);digitalWrite(pin,0);}
|
||||
// void on() {digitalWrite(pin,HIGH);onState=true;}
|
||||
// void off() {digitalWrite(pin,LOW);onState=false;}
|
||||
// int getPin() {return(pin);}
|
||||
//};
|
||||
|
||||
////////////////////////////////
|
||||
// Blinker //
|
||||
////////////////////////////////
|
||||
|
||||
class Blinker {
|
||||
|
||||
timer_group_t group;
|
||||
timer_idx_t idx;
|
||||
int pin;
|
||||
|
||||
int nBlinks;
|
||||
int onTime;
|
||||
int offTime;
|
||||
int delayTime;
|
||||
int count;
|
||||
|
||||
unsigned long pauseDuration;
|
||||
unsigned long pauseTime;
|
||||
boolean isPaused=false;
|
||||
|
||||
static void isrTimer(void *arg);
|
||||
|
||||
public:
|
||||
|
||||
Blinker();
|
||||
Blinker(int pin, int timerNum=0, uint16_t autoOffDuration=0);
|
||||
|
||||
// Creates a generic blinking LED on specified pin controlled
|
||||
// in background via interrupts generated by an ESP32 Alarm Timer.
|
||||
//class Blinker {
|
||||
//
|
||||
// timer_group_t group;
|
||||
// timer_idx_t idx;
|
||||
//
|
||||
// In the first form, a Blinker is instantiated without specifying
|
||||
// the pin. In this case the pin must be specified in a subsequent call
|
||||
// to init() before the Blinker can be used.
|
||||
// Blinkable *led;
|
||||
//
|
||||
// In the second form, a Blinker is instantiated and initialized with
|
||||
// the specified pin, obviating the need for a separate call to init().
|
||||
// int nBlinks;
|
||||
// int onTime;
|
||||
// int offTime;
|
||||
// int delayTime;
|
||||
// int count;
|
||||
//
|
||||
// unsigned long pauseDuration;
|
||||
// unsigned long pauseTime;
|
||||
// boolean isPaused=false;
|
||||
//
|
||||
// pin: Pin mumber to control. Blinker will set pinMode to OUTPUT automatically
|
||||
// static void isrTimer(void *arg);
|
||||
//
|
||||
// timerNum: ESP32 Alarm Timer to use.
|
||||
// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
||||
// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
||||
// public:
|
||||
//
|
||||
// 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 init(int pin, int timerNum=0, uint16_t autoOffDuration=0);
|
||||
|
||||
// Initializes Blinker, if not configured during instantiation.
|
||||
// Blinker(Blinkable *led, int timerNum=0, uint16_t autoOffDuration=0);
|
||||
//
|
||||
// pin: Pin mumber to control. Blinker will set pinMode to OUTPUT automatically
|
||||
//// Creates a generic blinking LED on specified pin controlled
|
||||
//// in background via interrupts generated by an ESP32 Alarm Timer.
|
||||
////
|
||||
//// In the first form, a Blinker is instantiated without specifying
|
||||
//// the pin. In this case the pin must be specified in a subsequent call
|
||||
//// to init() before the Blinker can be used.
|
||||
////
|
||||
//// In the second form, a Blinker is instantiated and initialized with
|
||||
//// the specified pin, obviating the need for a separate call to init().
|
||||
////
|
||||
//// led: An initialized LED device that implements the Blinkable Interface
|
||||
////
|
||||
//// timerNum: ESP32 Alarm Timer to use.
|
||||
//// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
||||
//// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
||||
////
|
||||
//// 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%)
|
||||
//
|
||||
// timerNum: ESP32 Alarm Timer to use.
|
||||
// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
||||
// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
||||
// void start(int period, float dutyCycle, int nBlinks, int delayTime);
|
||||
//
|
||||
// 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.
|
||||
//// 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
|
||||
//
|
||||
// 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.
|
||||
// void stop();
|
||||
//
|
||||
// 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)
|
||||
|
||||
|
||||
};
|
||||
//// 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
|
||||
//
|
||||
//};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,176 @@
|
|||
/*********************************************************************************
|
||||
* 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.
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "Blinker.h"
|
||||
|
||||
////////////////////////////////
|
||||
// Blinker //
|
||||
////////////////////////////////
|
||||
|
||||
Blinker::Blinker(Blinkable *led, int timerNum, uint16_t autoOffDuration){
|
||||
|
||||
this->led=led;
|
||||
|
||||
pauseDuration=autoOffDuration*1000;
|
||||
|
||||
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP>1 // ESP32 and ESP32-S2 contains two timers per timer group
|
||||
group=((timerNum/2)%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
||||
idx=(timerNum%2==0)?TIMER_0:TIMER_1; // ESP32-C3 only contains one timer per timer group
|
||||
#else
|
||||
group=(timerNum%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
||||
idx=TIMER_0;
|
||||
#endif
|
||||
|
||||
timer_config_t conf;
|
||||
conf.alarm_en=TIMER_ALARM_EN;
|
||||
conf.counter_en=TIMER_PAUSE;
|
||||
conf.intr_type=TIMER_INTR_LEVEL;
|
||||
conf.counter_dir=TIMER_COUNT_UP;
|
||||
conf.auto_reload=TIMER_AUTORELOAD_EN;
|
||||
conf.divider=getApbFrequency()/10000; // set divider to yield 10 kHz clock (0.1 ms pulses)
|
||||
|
||||
#ifdef SOC_TIMER_GROUP_SUPPORT_XTAL // set clock to APB (default is XTAL!) if clk_src is defined in conf structure
|
||||
conf.clk_src=TIMER_SRC_CLK_APB;
|
||||
#endif
|
||||
|
||||
timer_init(group,idx,&conf);
|
||||
timer_isr_register(group,idx,Blinker::isrTimer,(void *)this,0,NULL);
|
||||
timer_enable_intr(group,idx);
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::isrTimer(void *arg){
|
||||
|
||||
Blinker *b=(Blinker *)arg;
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) // use new method that is generic to ESP32, S2, and C3
|
||||
timer_group_clr_intr_status_in_isr(b->group,b->idx);
|
||||
#else // use older method that is only for ESP32
|
||||
if(b->group){
|
||||
if(b->idx)
|
||||
TIMERG1.int_clr_timers.t1=1;
|
||||
else
|
||||
TIMERG1.int_clr_timers.t0=1;
|
||||
} else {
|
||||
if(b->idx)
|
||||
TIMERG0.int_clr_timers.t1=1;
|
||||
else
|
||||
TIMERG0.int_clr_timers.t0=1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!(b->led->isOn())){
|
||||
b->led->on();
|
||||
timer_set_alarm_value(b->group,b->idx,b->onTime);
|
||||
b->count--;
|
||||
} else {
|
||||
b->led->off();
|
||||
if(b->count){
|
||||
timer_set_alarm_value(b->group,b->idx,b->offTime);
|
||||
} else {
|
||||
timer_set_alarm_value(b->group,b->idx,b->delayTime);
|
||||
b->count=b->nBlinks;
|
||||
}
|
||||
}
|
||||
|
||||
timer_set_alarm(b->group,b->idx,TIMER_ALARM_EN);
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::start(int period, float dutyCycle){
|
||||
|
||||
start(period, dutyCycle, 1, 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::start(int period, float dutyCycle, int nBlinks, int delayTime){
|
||||
|
||||
pauseTime=millis();
|
||||
isPaused=false;
|
||||
|
||||
period*=10;
|
||||
onTime=dutyCycle*period;
|
||||
offTime=period-onTime;
|
||||
this->delayTime=delayTime*10+offTime;
|
||||
this->nBlinks=nBlinks;
|
||||
count=nBlinks;
|
||||
timer_set_counter_value(group,idx,0);
|
||||
timer_set_alarm_value(group,idx,0);
|
||||
timer_start(group,idx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::stop(){
|
||||
|
||||
timer_pause(group,idx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::on(){
|
||||
|
||||
pauseTime=millis();
|
||||
isPaused=false;
|
||||
|
||||
stop();
|
||||
led->on();
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::off(){
|
||||
|
||||
pauseTime=millis();
|
||||
isPaused=false;
|
||||
|
||||
stop();
|
||||
led->off();
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void Blinker::check(){
|
||||
|
||||
if(pauseDuration==0 || isPaused || (millis()-pauseTime)<pauseDuration)
|
||||
return;
|
||||
|
||||
Serial.print("Pausing Status LED\n");
|
||||
isPaused=true;
|
||||
led->off();
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
int Blinker::getPin(){
|
||||
return(led->getPin());
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
/*********************************************************************************
|
||||
* 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 {
|
||||
protected:
|
||||
boolean onState=false;
|
||||
|
||||
public:
|
||||
virtual void on()=0;
|
||||
virtual void off()=0;
|
||||
virtual int getPin()=0;
|
||||
boolean isOn() {return(onState);}
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Generic_LED //
|
||||
////////////////////////////////
|
||||
|
||||
class LED : public Blinkable {
|
||||
int pin;
|
||||
|
||||
public:
|
||||
|
||||
LED(int pin) : pin{pin} {pinMode(pin,OUTPUT);digitalWrite(pin,0);}
|
||||
void on() {digitalWrite(pin,HIGH);onState=true;}
|
||||
void off() {digitalWrite(pin,LOW);onState=false;}
|
||||
int getPin() {return(pin);}
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Blinker //
|
||||
////////////////////////////////
|
||||
|
||||
class Blinker {
|
||||
|
||||
timer_group_t group;
|
||||
timer_idx_t idx;
|
||||
|
||||
Blinkable *led;
|
||||
|
||||
int nBlinks;
|
||||
int onTime;
|
||||
int offTime;
|
||||
int delayTime;
|
||||
int count;
|
||||
|
||||
unsigned long pauseDuration;
|
||||
unsigned long pauseTime;
|
||||
boolean isPaused=false;
|
||||
|
||||
static void isrTimer(void *arg);
|
||||
|
||||
public:
|
||||
|
||||
Blinker(Blinkable *led, int timerNum=0, uint16_t autoOffDuration=0);
|
||||
|
||||
// Creates a generic blinking LED on specified pin controlled
|
||||
// in background via interrupts generated by an ESP32 Alarm Timer.
|
||||
//
|
||||
// In the first form, a Blinker is instantiated without specifying
|
||||
// the pin. In this case the pin must be specified in a subsequent call
|
||||
// to init() before the Blinker can be used.
|
||||
//
|
||||
// In the second form, a Blinker is instantiated and initialized with
|
||||
// the specified pin, obviating the need for a separate call to init().
|
||||
//
|
||||
// led: An initialized LED device that implements the Blinkable Interface
|
||||
//
|
||||
// timerNum: ESP32 Alarm Timer to use.
|
||||
// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
||||
// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
||||
//
|
||||
// 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
|
||||
|
||||
};
|
||||
|
|
@ -33,12 +33,13 @@
|
|||
|
||||
#include "RFControl.h"
|
||||
#include "PwmPin.h"
|
||||
#include "Blinker.h"
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Single-Wire RGB/RGBW NeoPixels //
|
||||
////////////////////////////////////////////
|
||||
|
||||
class Pixel {
|
||||
class Pixel : Blinkable {
|
||||
|
||||
public:
|
||||
struct Color {
|
||||
|
|
|
|||
10
src/src.ino
10
src/src.ino
|
|
@ -3,6 +3,9 @@
|
|||
// as well as compile and test from this point. This file is ignored when the library is included in other sketches.
|
||||
|
||||
#include "HomeSpan.h"
|
||||
#include "FeatherPins.h"
|
||||
#include "extras/Pixel.h"
|
||||
#include "extras/Blinker.h"
|
||||
|
||||
#define STRING_t const char * // WORK-AROUND
|
||||
|
||||
|
|
@ -14,8 +17,11 @@ void setup() {
|
|||
Serial.begin(115200);
|
||||
|
||||
// homeSpan.setLogLevel(2);
|
||||
// homeSpan.setStatusPin(13);
|
||||
homeSpan.setControlPin(33);
|
||||
homeSpan.setControlPin(F25);
|
||||
homeSpan.setStatusPin(F26);
|
||||
// homeSpan.setStatusPin(new LED(F26));
|
||||
|
||||
// new Pixel(F27);
|
||||
|
||||
homeSpan.setHostNameSuffix("-lamp1");
|
||||
homeSpan.setPortNum(1201);
|
||||
|
|
|
|||
Loading…
Reference in New Issue