Jeśli nie to zrobię PR
Code: Select all
/*
Copyright (C) AC SOFTWARE SP. Z O.O
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "blinking_led.h"
#include <supla/auto_lock.h>
#include <supla/io.h>
#include <supla/log_wrapper.h>
#include <supla/mutex.h>
#include <supla/time.h>
#ifdef ARDUINO_ARCH_ESP32
#include <Arduino.h>
#endif
using Supla::Control::BlinkingLed;
BlinkingLed::BlinkingLed(Supla::Io::Base *io, uint8_t outPin, bool invert)
: BlinkingLed(outPin, invert) {
this->io = io;
}
BlinkingLed::BlinkingLed(uint8_t outPin, bool invert)
: outPin(outPin), invert(invert) {
mutex = Supla::Mutex::Create();
}
void BlinkingLed::onInit() {
Supla::AutoLock autoLock(mutex);
if (state == NOT_INITIALIZED) {
turnOff();
}
// Skip pinMode for RGB LEDs - they have special handling
if (!isRgbLed()) {
Supla::Io::pinMode(outPin, OUTPUT, io);
}
lastUpdate = 0;
updatePin();
}
void BlinkingLed::onTimer() {
Supla::AutoLock autoLock(mutex);
updatePin();
}
void BlinkingLed::setInvertedLogic(bool invertedLogic) {
Supla::AutoLock autoLock(mutex);
invert = invertedLogic;
updatePin();
}
void BlinkingLed::setAlwaysOffSequence() {
setCustomSequence(0, 1000);
}
void BlinkingLed::setAlwaysOnSequence() {
setCustomSequence(1000, 0);
}
void BlinkingLed::turnOn() {
lastUpdate = millis();
state = ON;
#ifdef ARDUINO_ARCH_ESP32
if (isRgbLed()) {
// For RGB LEDs, write white color when ON
uint8_t brightness = invert ? 0 : 255;
rgbLedWrite(outPin, brightness, brightness, brightness);
} else {
Supla::Io::digitalWrite(outPin, invert ? 0 : 1, io);
}
#else
Supla::Io::digitalWrite(outPin, invert ? 0 : 1, io);
#endif
auto copy = copyStateTo;
if (copy) {
copy->turnOn();
}
}
void BlinkingLed::turnOff() {
lastUpdate = millis();
state = OFF;
#ifdef ARDUINO_ARCH_ESP32
if (isRgbLed()) {
// For RGB LEDs, write zero brightness when OFF
uint8_t brightness = invert ? 255 : 0;
rgbLedWrite(outPin, brightness, brightness, brightness);
} else {
Supla::Io::digitalWrite(outPin, invert ? 1 : 0, io);
}
#else
Supla::Io::digitalWrite(outPin, invert ? 1 : 0, io);
#endif
auto copy = copyStateTo;
if (copy) {
copy->turnOff();
}
}
void BlinkingLed::updatePin() {
if (!enabled) {
return;
}
if (onDuration == 0 || offDuration == 0) {
if ((state == ON || state == NOT_INITIALIZED) && onDuration == 0) {
turnOff();
}
if ((state == OFF || state == NOT_INITIALIZED) && offDuration == 0) {
turnOn();
}
return;
}
if (state == ON && millis() - lastUpdate > onDuration) {
turnOff();
} else if (state == OFF) {
if (onLimit > 0 && pauseDuration > 0 && onLimitCounter == 0 &&
millis() - lastUpdate < pauseDuration && lastUpdate != 0) {
return;
}
if (millis() - lastUpdate > offDuration || lastUpdate == 0) {
if (onLimit > 0 && pauseDuration > 0 && onLimitCounter == 0) {
onLimitCounter = onLimit;
if (repeatLimit > 0) {
if (repeatLimit == 1) {
onDuration = 0;
offDuration = 1000;
onLimit = 0;
return;
}
repeatLimit--;
}
}
turnOn();
if (onLimitCounter > 0) {
onLimitCounter--;
}
}
}
}
void BlinkingLed::setCustomSequence(uint32_t onDurationMs,
uint32_t offDurationMs,
uint32_t pauseDurrationMs,
uint8_t onLimit,
uint8_t repeatLimit,
bool startWithOff) {
Supla::AutoLock autoLock(mutex);
enable();
onDuration = onDurationMs;
offDuration = offDurationMs;
pauseDuration = pauseDurrationMs;
this->onLimit = onLimit;
onLimitCounter = onLimit;
this->repeatLimit = repeatLimit;
lastUpdate = 0;
autoLock.unlock();
if (startWithOff && offDuration > 0) {
turnOff();
} else if (onDuration > 0) {
turnOn();
} else {
turnOff();
}
updatePin();
}
void BlinkingLed::setCopyStateTo(BlinkingLed *led) {
copyStateTo = led;
if (copyStateTo != nullptr) {
copyStateTo->disable();
updatePin();
}
}
void BlinkingLed::disable() {
enabled = false;
}
void BlinkingLed::enable() {
enabled = true;
}
bool BlinkingLed::isRgbLed() {
#ifdef ARDUINO_ARCH_ESP32
// ESP32-S3 has RGB LED on GPIO48
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C3
return true;
#endif
#else
return false;
#endif
}
