diff --git a/src/extras/Blinker.cpp b/src/extras/Blinker.cpp index dad0ca2..9e65d48 100644 --- a/src/extras/Blinker.cpp +++ b/src/extras/Blinker.cpp @@ -31,76 +31,27 @@ // Blinker // //////////////////////////////// -Blinker::Blinker(Blinkable *led, int timerNum, uint16_t autoOffDuration){ - +Blinker::Blinker(Blinkable *led, 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){ +void Blinker::blinkTask(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; + for(;;){ + for(int i=0;inBlinks;i++){ + b->led->on(); + delay(b->onTime); + b->led->off(); + delay(b->offTime); } + delay(b->delayTime); } - timer_set_alarm(b->group,b->idx,TIMER_ALARM_EN); - } ////////////////////////////////////// @@ -113,46 +64,48 @@ void Blinker::start(int period, float dutyCycle){ ////////////////////////////////////// void Blinker::start(int period, float dutyCycle, int nBlinks, int delayTime){ + + onTime=dutyCycle*period; + offTime=period-onTime; + this->delayTime=delayTime+offTime; + this->nBlinks=nBlinks; + + stop(); + Serial.printf("Starting Blink Task\n"); + xTaskCreate( blinkTask, "BlinkTask", 1024, (void *)this, 0, &blinkHandle ); 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); + if(blinkHandle!=NULL){ + Serial.printf("Deleting Blink Task\n"); + vTaskDelete(blinkHandle); + blinkHandle=NULL; + } + + isPaused=true; } ////////////////////////////////////// void Blinker::on(){ - pauseTime=millis(); - isPaused=false; - stop(); led->on(); + + pauseTime=millis(); + isPaused=false; } ////////////////////////////////////// void Blinker::off(){ - pauseTime=millis(); - isPaused=false; - stop(); led->off(); } @@ -164,9 +117,8 @@ void Blinker::check(){ if(pauseDuration==0 || isPaused || (millis()-pauseTime)off(); + Serial.print("Pausing LED\n"); + off(); } ////////////////////////////////////// diff --git a/src/extras/Blinker.h b/src/extras/Blinker.h index 9794d6b..16994ee 100644 --- a/src/extras/Blinker.h +++ b/src/extras/Blinker.h @@ -35,14 +35,11 @@ //////////////////////////////// class Blinkable { - protected: - boolean onState=false; - public: + virtual void on()=0; virtual void off()=0; virtual int getPin()=0; - boolean isOn() {return(onState);} }; //////////////////////////////// @@ -53,10 +50,10 @@ 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;} + void on() {digitalWrite(pin,HIGH);} + void off() {digitalWrite(pin,LOW);} int getPin() {return(pin);} }; @@ -66,43 +63,28 @@ class LED : public Blinkable { class Blinker { - timer_group_t group; - timer_idx_t idx; - + TaskHandle_t blinkHandle = NULL; 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); + static void blinkTask(void *arg); public: - Blinker(Blinkable *led, int timerNum=0, uint16_t autoOffDuration=0); + Blinker(Blinkable *led, 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(). +// Creates a generic blinking LED in a separate task thread // // 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 diff --git a/src/extras/Pixel.h b/src/extras/Pixel.h index 27d431c..facd92d 100644 --- a/src/extras/Pixel.h +++ b/src/extras/Pixel.h @@ -39,7 +39,7 @@ // Single-Wire RGB/RGBW NeoPixels // //////////////////////////////////////////// -class Pixel : Blinkable { +class Pixel : public Blinkable { public: struct Color { @@ -152,6 +152,9 @@ class Pixel : Blinkable { operator bool(){ // override boolean operator to return true/false if creation succeeded/failed return(*rf); } + + void on() {set(RGB(255,0,0));} + void off() {set(RGB(0,0,0));} }; //////////////////////////////////////////// diff --git a/src/extras/extras.ino b/src/extras/extras.ino index 8d47d19..3fd3fc5 100644 --- a/src/extras/extras.ino +++ b/src/extras/extras.ino @@ -1,13 +1,11 @@ // This is a placeholder .ino file that allows you to easily edit the contents of this files using the Arduino IDE, // as well as compile and test from this point. This file is ignored when the library is included in other sketches. +#include "Blinker.h" #include "Pixel.h" -//#define PixelType Pixel -#define PixelType Dot - -//Pixel p(8); -Dot p(0,1); +//Blinker p(new LED(26)); +Blinker p(new Pixel(27),20); void setup() { @@ -15,29 +13,21 @@ void setup() { Serial.flush(); delay(1000); // wait for interface to flush - Serial.println("\n\nHomeSpan Pixel Example\n"); + Serial.println("\n\nHomeSpan Blinker Example\n"); +// Serial.printf("Pins = %d %d\n",b.getPin(),p.getPin()); - PixelType::Color off=PixelType::RGB(0,0,0); - - p.set(PixelType::RGB(0,0,255),3); - delay(1000); - - p.set(off,3); - delay(1000); - - PixelType::Color c[]={p.HSV(120,100,30),p.HSV(0,0,0),p.HSV(0,0,0)}; - p.set(c,3); - delay(1000); - - c[0].HSV(0,0,0); - c[1].HSV(60,100,30); - p.set(c,3); - delay(1000); - - c[1].HSV(0,0,0); - c[2].HSV(0,100,30); - p.set(c,3); + p.on(); + delay(2000); + p.off(); + delay(2000); + p.start(300,0.25,4,1000); + delay(5000); + Serial.printf("New Pattern\n"); + p.start(200,0.2,2,200); + delay(3000); + p.off(); } void loop(){ + p.check(); }