forked from xiaozhi/xiaozhi-esp32
reconstruct led control
This commit is contained in:
218
main/led/circular_strip.cc
Normal file
218
main/led/circular_strip.cc
Normal file
@@ -0,0 +1,218 @@
|
||||
#include "circular_strip.h"
|
||||
#include "application.h"
|
||||
#include <esp_log.h>
|
||||
|
||||
#define TAG "CircularStrip"
|
||||
|
||||
#define DEFAULT_BRIGHTNESS 4
|
||||
#define HIGH_BRIGHTNESS 16
|
||||
#define LOW_BRIGHTNESS 1
|
||||
|
||||
#define BLINK_INFINITE -1
|
||||
|
||||
CircularStrip::CircularStrip(gpio_num_t gpio, uint8_t max_leds) : max_leds_(max_leds) {
|
||||
// If the gpio is not connected, you should use NoLed class
|
||||
assert(gpio != GPIO_NUM_NC);
|
||||
|
||||
colors_.resize(max_leds_);
|
||||
|
||||
led_strip_config_t strip_config = {};
|
||||
strip_config.strip_gpio_num = gpio;
|
||||
strip_config.max_leds = max_leds_;
|
||||
strip_config.led_pixel_format = LED_PIXEL_FORMAT_GRB;
|
||||
strip_config.led_model = LED_MODEL_WS2812;
|
||||
|
||||
led_strip_rmt_config_t rmt_config = {};
|
||||
rmt_config.resolution_hz = 10 * 1000 * 1000; // 10MHz
|
||||
|
||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip_));
|
||||
led_strip_clear(led_strip_);
|
||||
|
||||
esp_timer_create_args_t strip_timer_args = {
|
||||
.callback = [](void *arg) {
|
||||
auto strip = static_cast<CircularStrip*>(arg);
|
||||
std::lock_guard<std::mutex> lock(strip->mutex_);
|
||||
if (strip->strip_callback_ != nullptr) {
|
||||
strip->strip_callback_();
|
||||
}
|
||||
},
|
||||
.arg = this,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "Strip Timer",
|
||||
.skip_unhandled_events = false,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&strip_timer_args, &strip_timer_));
|
||||
}
|
||||
|
||||
CircularStrip::~CircularStrip() {
|
||||
esp_timer_stop(strip_timer_);
|
||||
if (led_strip_ != nullptr) {
|
||||
led_strip_del(led_strip_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CircularStrip::StaticColor(StripColor color) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(strip_timer_);
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
colors_[i] = color;
|
||||
led_strip_set_pixel(led_strip_, i, color.red, color.green, color.blue);
|
||||
}
|
||||
led_strip_refresh(led_strip_);
|
||||
}
|
||||
|
||||
void CircularStrip::Blink(StripColor color, int interval_ms) {
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
colors_[i] = color;
|
||||
}
|
||||
StartStripTask(interval_ms, [this]() {
|
||||
static bool on = true;
|
||||
if (on) {
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue);
|
||||
}
|
||||
led_strip_refresh(led_strip_);
|
||||
} else {
|
||||
led_strip_clear(led_strip_);
|
||||
}
|
||||
on = !on;
|
||||
});
|
||||
}
|
||||
|
||||
void CircularStrip::FadeOut(int interval_ms) {
|
||||
StartStripTask(interval_ms, [this]() {
|
||||
bool all_off = true;
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
colors_[i].red /= 2;
|
||||
colors_[i].green /= 2;
|
||||
colors_[i].blue /= 2;
|
||||
if (colors_[i].red != 0 || colors_[i].green != 0 || colors_[i].blue != 0) {
|
||||
all_off = false;
|
||||
}
|
||||
led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue);
|
||||
}
|
||||
if (all_off) {
|
||||
led_strip_clear(led_strip_);
|
||||
esp_timer_stop(strip_timer_);
|
||||
} else {
|
||||
led_strip_refresh(led_strip_);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CircularStrip::Breathe(StripColor low, StripColor high, int interval_ms) {
|
||||
StartStripTask(interval_ms, [this, low, high]() {
|
||||
static bool increase = true;
|
||||
static StripColor color = low;
|
||||
if (increase) {
|
||||
if (color.red < high.red) {
|
||||
color.red++;
|
||||
}
|
||||
if (color.green < high.green) {
|
||||
color.green++;
|
||||
}
|
||||
if (color.blue < high.blue) {
|
||||
color.blue++;
|
||||
}
|
||||
if (color.red == high.red && color.green == high.green && color.blue == high.blue) {
|
||||
increase = false;
|
||||
}
|
||||
} else {
|
||||
if (color.red > low.red) {
|
||||
color.red--;
|
||||
}
|
||||
if (color.green > low.green) {
|
||||
color.green--;
|
||||
}
|
||||
if (color.blue > low.blue) {
|
||||
color.blue--;
|
||||
}
|
||||
if (color.red == low.red && color.green == low.green && color.blue == low.blue) {
|
||||
increase = true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
led_strip_set_pixel(led_strip_, i, color.red, color.green, color.blue);
|
||||
}
|
||||
led_strip_refresh(led_strip_);
|
||||
});
|
||||
}
|
||||
|
||||
void CircularStrip::Scroll(StripColor low, StripColor high, int length, int interval_ms) {
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
colors_[i] = low;
|
||||
}
|
||||
StartStripTask(interval_ms, [this, low, high, length]() {
|
||||
static int offset = 0;
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
colors_[i] = low;
|
||||
}
|
||||
for (int j = 0; j < length; j++) {
|
||||
int i = (offset + j) % max_leds_;
|
||||
colors_[i] = high;
|
||||
}
|
||||
for (int i = 0; i < max_leds_; i++) {
|
||||
led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue);
|
||||
}
|
||||
led_strip_refresh(led_strip_);
|
||||
offset = (offset + 1) % max_leds_;
|
||||
});
|
||||
}
|
||||
|
||||
void CircularStrip::StartStripTask(int interval_ms, std::function<void()> cb) {
|
||||
if (led_strip_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(strip_timer_);
|
||||
|
||||
strip_callback_ = cb;
|
||||
esp_timer_start_periodic(strip_timer_, interval_ms * 1000);
|
||||
}
|
||||
|
||||
|
||||
void CircularStrip::OnStateChanged() {
|
||||
auto& app = Application::GetInstance();
|
||||
auto device_state = app.GetDeviceState();
|
||||
switch (device_state) {
|
||||
case kDeviceStateStarting: {
|
||||
StripColor low = { 0, 0, 0 };
|
||||
StripColor high = { LOW_BRIGHTNESS, LOW_BRIGHTNESS, DEFAULT_BRIGHTNESS };
|
||||
Scroll(low, high, 3, 100);
|
||||
break;
|
||||
}
|
||||
case kDeviceStateWifiConfiguring: {
|
||||
StripColor color = { LOW_BRIGHTNESS, LOW_BRIGHTNESS, DEFAULT_BRIGHTNESS };
|
||||
Blink(color, 500);
|
||||
break;
|
||||
}
|
||||
case kDeviceStateIdle:
|
||||
FadeOut(50);
|
||||
break;
|
||||
case kDeviceStateConnecting: {
|
||||
StripColor color = { LOW_BRIGHTNESS, LOW_BRIGHTNESS, DEFAULT_BRIGHTNESS };
|
||||
StaticColor(color);
|
||||
break;
|
||||
}
|
||||
case kDeviceStateListening: {
|
||||
StripColor color = { DEFAULT_BRIGHTNESS, LOW_BRIGHTNESS, LOW_BRIGHTNESS };
|
||||
StaticColor(color);
|
||||
break;
|
||||
}
|
||||
case kDeviceStateSpeaking: {
|
||||
StripColor color = { LOW_BRIGHTNESS, DEFAULT_BRIGHTNESS, LOW_BRIGHTNESS };
|
||||
StaticColor(color);
|
||||
break;
|
||||
}
|
||||
case kDeviceStateUpgrading: {
|
||||
StripColor color = { LOW_BRIGHTNESS, DEFAULT_BRIGHTNESS, LOW_BRIGHTNESS };
|
||||
Blink(color, 100);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ESP_LOGE(TAG, "Invalid led strip event: %d", device_state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
44
main/led/circular_strip.h
Normal file
44
main/led/circular_strip.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef _CIRCULAR_STRIP_H_
|
||||
#define _CIRCULAR_STRIP_H_
|
||||
|
||||
#include "led.h"
|
||||
#include <driver/gpio.h>
|
||||
#include <led_strip.h>
|
||||
#include <esp_timer.h>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
struct StripColor {
|
||||
uint8_t red = 0, green = 0, blue = 0;
|
||||
};
|
||||
|
||||
class CircularStrip : public Led {
|
||||
public:
|
||||
CircularStrip(gpio_num_t gpio, uint8_t max_leds);
|
||||
virtual ~CircularStrip();
|
||||
|
||||
void OnStateChanged() override;
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
TaskHandle_t blink_task_ = nullptr;
|
||||
led_strip_handle_t led_strip_ = nullptr;
|
||||
int max_leds_ = 0;
|
||||
std::vector<StripColor> colors_;
|
||||
int blink_counter_ = 0;
|
||||
int blink_interval_ms_ = 0;
|
||||
esp_timer_handle_t strip_timer_ = nullptr;
|
||||
std::function<void()> strip_callback_ = nullptr;
|
||||
|
||||
void StartStripTask(int interval_ms, std::function<void()> cb);
|
||||
|
||||
void StaticColor(StripColor color);
|
||||
void Blink(StripColor color, int interval_ms);
|
||||
void Breathe(StripColor low, StripColor high, int interval_ms);
|
||||
void Rainbow(StripColor low, StripColor high, int interval_ms);
|
||||
void Scroll(StripColor low, StripColor high, int length, int interval_ms);
|
||||
void FadeOut(int interval_ms);
|
||||
};
|
||||
|
||||
#endif // _CIRCULAR_STRIP_H_
|
||||
219
main/led/led.cc
Normal file
219
main/led/led.cc
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "led.h"
|
||||
#include "board.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <esp_log.h>
|
||||
|
||||
#define TAG "Led"
|
||||
|
||||
Led::Led(gpio_num_t gpio, uint8_t max_leds) {
|
||||
if (gpio == GPIO_NUM_NC) {
|
||||
ESP_LOGI(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
led_ = new Led(gpio, max_leds);
|
||||
|
||||
esp_timer_create_args_t led_strip_timer_args = {
|
||||
.callback = [](void *arg) {
|
||||
auto light = static_cast<LedStripWrapper*>(arg);
|
||||
light->OnBlinkTimer();
|
||||
},
|
||||
.arg = this,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "Led Strip Timer",
|
||||
.skip_unhandled_events = false,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&led_strip_timer_args, &led_strip_timer_));
|
||||
}
|
||||
|
||||
LedStripWrapper::~LedStripWrapper() {
|
||||
if (led_strip_timer_ != nullptr) {
|
||||
esp_timer_delete(led_strip_timer_);
|
||||
}
|
||||
if (led_ != nullptr) {
|
||||
delete led_;
|
||||
}
|
||||
}
|
||||
|
||||
void LedStripWrapper::OnBlinkTimer() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
counter_--;
|
||||
timer_callback_();
|
||||
}
|
||||
|
||||
void LedStripWrapper::SetLedBasicColor(LedBasicColor color, uint8_t brightness) {
|
||||
if (led_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (color) {
|
||||
case kLedColorWhite:
|
||||
led_->SetWhite(brightness);
|
||||
break;
|
||||
case kLedColorGrey:
|
||||
led_->SetGrey(brightness);
|
||||
break;
|
||||
case kLedColorRed:
|
||||
led_->SetRed(brightness);
|
||||
break;
|
||||
case kLedColorGreen:
|
||||
led_->SetGreen(brightness);
|
||||
break;
|
||||
case kLedColorBlue:
|
||||
led_->SetBlue(brightness);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LedStripWrapper::SetLedStripBasicColor(uint8_t index, LedBasicColor color, uint8_t brightness) {
|
||||
if (led_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index >= led_->max_leds()) {
|
||||
ESP_LOGE(TAG, "Invalid led index: %d", index);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (color) {
|
||||
case kLedColorWhite:
|
||||
led_strip_set_pixel(led_->led_strip(), index, brightness, brightness, brightness);
|
||||
break;
|
||||
case kLedColorGrey:
|
||||
led_strip_set_pixel(led_->led_strip(), index, brightness, brightness, brightness);
|
||||
break;
|
||||
case kLedColorRed:
|
||||
led_strip_set_pixel(led_->led_strip(), index, brightness, 0, 0);
|
||||
break;
|
||||
case kLedColorGreen:
|
||||
led_strip_set_pixel(led_->led_strip(), index, 0, brightness, 0);
|
||||
break;
|
||||
case kLedColorBlue:
|
||||
led_strip_set_pixel(led_->led_strip(), index, 0, 0, brightness);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LedStripWrapper::StartBlinkTask(uint32_t times, uint32_t interval_ms) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (led_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_timer_stop(led_strip_timer_);
|
||||
counter_ = times * 2;
|
||||
timer_callback_ = [this]() {
|
||||
if (counter_ & 1) {
|
||||
led_->TurnOn();
|
||||
} else {
|
||||
led_->TurnOff();
|
||||
if (counter_ == 0) {
|
||||
esp_timer_stop(led_strip_timer_);
|
||||
}
|
||||
}
|
||||
};
|
||||
esp_timer_start_periodic(led_strip_timer_, interval_ms * 1000);
|
||||
}
|
||||
|
||||
void LedStripWrapper::BlinkOnce(LedBasicColor color, uint8_t brightness) {
|
||||
Blink(color, brightness, 1, 100);
|
||||
}
|
||||
|
||||
void LedStripWrapper::Blink(LedBasicColor color, uint32_t times, uint32_t interval_ms, uint8_t brightness) {
|
||||
SetLedBasicColor(color, brightness);
|
||||
StartBlinkTask(times, interval_ms);
|
||||
}
|
||||
|
||||
void LedStripWrapper::ContinuousBlink(LedBasicColor color, uint32_t interval_ms, uint8_t brightness) {
|
||||
SetLedBasicColor(color, brightness);
|
||||
StartBlinkTask(COUNTER_INFINITE, interval_ms);
|
||||
}
|
||||
|
||||
void LedStripWrapper::StaticLight(LedBasicColor color, uint8_t brightness) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (led_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
SetLedBasicColor(color, brightness);
|
||||
esp_timer_stop(led_strip_timer_);
|
||||
led_->TurnOn();
|
||||
}
|
||||
|
||||
void LedStripWrapper::ChasingLight(LedBasicColor base_color, LedBasicColor color, uint32_t interval_ms, uint8_t brightness) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (led_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_timer_stop(led_strip_timer_);
|
||||
counter_ = COUNTER_INFINITE;
|
||||
timer_callback_ = [this, base_color, color, brightness]() {
|
||||
auto index = counter_ % led_->max_leds();
|
||||
for (uint8_t i = 0; i < led_->max_leds(); i++) {
|
||||
if (i == index || i == (index + 1) % led_->max_leds()) {
|
||||
SetLedStripBasicColor(i, color, brightness);
|
||||
} else {
|
||||
SetLedStripBasicColor(i, base_color, LOW_BRIGHTNESS);
|
||||
}
|
||||
}
|
||||
led_strip_refresh(led_->led_strip());
|
||||
};
|
||||
esp_timer_start_periodic(led_strip_timer_, interval_ms * 1000);
|
||||
}
|
||||
|
||||
void LedStripWrapper::BreathLight(LedBasicColor color, uint32_t interval_ms) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (led_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_timer_stop(led_strip_timer_);
|
||||
counter_ = COUNTER_INFINITE;
|
||||
timer_callback_ = [this, color]() {
|
||||
static bool increase = true;
|
||||
static uint32_t brightness = LOW_BRIGHTNESS;
|
||||
|
||||
for (uint8_t i = 0; i < led_->max_leds(); i++) {
|
||||
SetLedStripBasicColor(i, color, brightness);
|
||||
}
|
||||
led_strip_refresh(led_->led_strip());
|
||||
|
||||
if (brightness == HIGH_BRIGHTNESS) {
|
||||
increase = false;
|
||||
} else if (brightness == LOW_BRIGHTNESS) {
|
||||
increase = true;
|
||||
}
|
||||
|
||||
if (increase) {
|
||||
brightness += 1;
|
||||
} else {
|
||||
brightness -= 1;
|
||||
}
|
||||
};
|
||||
esp_timer_start_periodic(led_strip_timer_, interval_ms * 1000);
|
||||
}
|
||||
|
||||
void LedStripWrapper::LightOff() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (led_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Builtin LED not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_timer_stop(led_strip_timer_);
|
||||
led_->TurnOff();
|
||||
}
|
||||
17
main/led/led.h
Normal file
17
main/led/led.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _LED_H_
|
||||
#define _LED_H_
|
||||
|
||||
class Led {
|
||||
public:
|
||||
virtual ~Led() = default;
|
||||
// Set the led state based on the device state
|
||||
virtual void OnStateChanged() = 0;
|
||||
};
|
||||
|
||||
|
||||
class NoLed : public Led {
|
||||
public:
|
||||
virtual void OnStateChanged() override {}
|
||||
};
|
||||
|
||||
#endif // _LED_H_
|
||||
158
main/led/single_led.cc
Normal file
158
main/led/single_led.cc
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "single_led.h"
|
||||
#include "application.h"
|
||||
#include <esp_log.h>
|
||||
|
||||
#define TAG "SingleLed"
|
||||
|
||||
#define DEFAULT_BRIGHTNESS 4
|
||||
#define HIGH_BRIGHTNESS 16
|
||||
#define LOW_BRIGHTNESS 2
|
||||
|
||||
#define BLINK_INFINITE -1
|
||||
|
||||
|
||||
SingleLed::SingleLed(gpio_num_t gpio) {
|
||||
// If the gpio is not connected, you should use NoLed class
|
||||
assert(gpio != GPIO_NUM_NC);
|
||||
|
||||
led_strip_config_t strip_config = {};
|
||||
strip_config.strip_gpio_num = gpio;
|
||||
strip_config.max_leds = 1;
|
||||
strip_config.led_pixel_format = LED_PIXEL_FORMAT_GRB;
|
||||
strip_config.led_model = LED_MODEL_WS2812;
|
||||
|
||||
led_strip_rmt_config_t rmt_config = {};
|
||||
rmt_config.resolution_hz = 10 * 1000 * 1000; // 10MHz
|
||||
|
||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip_));
|
||||
led_strip_clear(led_strip_);
|
||||
|
||||
esp_timer_create_args_t blink_timer_args = {
|
||||
.callback = [](void *arg) {
|
||||
auto led = static_cast<SingleLed*>(arg);
|
||||
led->OnBlinkTimer();
|
||||
},
|
||||
.arg = this,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "Blink Timer",
|
||||
.skip_unhandled_events = false,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&blink_timer_args, &blink_timer_));
|
||||
}
|
||||
|
||||
SingleLed::~SingleLed() {
|
||||
esp_timer_stop(blink_timer_);
|
||||
if (led_strip_ != nullptr) {
|
||||
led_strip_del(led_strip_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SingleLed::SetColor(uint8_t r, uint8_t g, uint8_t b) {
|
||||
r_ = r;
|
||||
g_ = g;
|
||||
b_ = b;
|
||||
}
|
||||
|
||||
void SingleLed::TurnOn() {
|
||||
if (led_strip_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(blink_timer_);
|
||||
led_strip_set_pixel(led_strip_, 0, r_, g_, b_);
|
||||
led_strip_refresh(led_strip_);
|
||||
}
|
||||
|
||||
void SingleLed::TurnOff() {
|
||||
if (led_strip_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(blink_timer_);
|
||||
led_strip_clear(led_strip_);
|
||||
}
|
||||
|
||||
void SingleLed::BlinkOnce() {
|
||||
Blink(1, 100);
|
||||
}
|
||||
|
||||
void SingleLed::Blink(int times, int interval_ms) {
|
||||
StartBlinkTask(times, interval_ms);
|
||||
}
|
||||
|
||||
void SingleLed::StartContinuousBlink(int interval_ms) {
|
||||
StartBlinkTask(BLINK_INFINITE, interval_ms);
|
||||
}
|
||||
|
||||
void SingleLed::StartBlinkTask(int times, int interval_ms) {
|
||||
if (led_strip_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(blink_timer_);
|
||||
|
||||
blink_counter_ = times * 2;
|
||||
blink_interval_ms_ = interval_ms;
|
||||
esp_timer_start_periodic(blink_timer_, interval_ms * 1000);
|
||||
}
|
||||
|
||||
void SingleLed::OnBlinkTimer() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
blink_counter_--;
|
||||
if (blink_counter_ & 1) {
|
||||
led_strip_set_pixel(led_strip_, 0, r_, g_, b_);
|
||||
led_strip_refresh(led_strip_);
|
||||
} else {
|
||||
led_strip_clear(led_strip_);
|
||||
|
||||
if (blink_counter_ == 0) {
|
||||
esp_timer_stop(blink_timer_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SingleLed::OnStateChanged() {
|
||||
auto& app = Application::GetInstance();
|
||||
auto device_state = app.GetDeviceState();
|
||||
switch (device_state) {
|
||||
case kDeviceStateStarting:
|
||||
SetColor(0, 0, DEFAULT_BRIGHTNESS);
|
||||
StartContinuousBlink(100);
|
||||
break;
|
||||
case kDeviceStateWifiConfiguring:
|
||||
SetColor(0, 0, DEFAULT_BRIGHTNESS);
|
||||
StartContinuousBlink(500);
|
||||
break;
|
||||
case kDeviceStateIdle:
|
||||
TurnOff();
|
||||
break;
|
||||
case kDeviceStateConnecting:
|
||||
SetColor(0, 0, DEFAULT_BRIGHTNESS);
|
||||
TurnOn();
|
||||
break;
|
||||
case kDeviceStateListening:
|
||||
if (app.IsVoiceDetected()) {
|
||||
SetColor(HIGH_BRIGHTNESS, 0, 0);
|
||||
} else {
|
||||
SetColor(LOW_BRIGHTNESS, 0, 0);
|
||||
}
|
||||
TurnOn();
|
||||
break;
|
||||
case kDeviceStateSpeaking:
|
||||
SetColor(0, DEFAULT_BRIGHTNESS, 0);
|
||||
TurnOn();
|
||||
break;
|
||||
case kDeviceStateUpgrading:
|
||||
SetColor(0, DEFAULT_BRIGHTNESS, 0);
|
||||
StartContinuousBlink(100);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Invalid led strip event: %d", device_state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
38
main/led/single_led.h
Normal file
38
main/led/single_led.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef _SINGLE_LED_H_
|
||||
#define _SINGLE_LED_H_
|
||||
|
||||
#include "led.h"
|
||||
#include <driver/gpio.h>
|
||||
#include <led_strip.h>
|
||||
#include <esp_timer.h>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
class SingleLed : public Led {
|
||||
public:
|
||||
SingleLed(gpio_num_t gpio);
|
||||
virtual ~SingleLed();
|
||||
|
||||
void OnStateChanged() override;
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
TaskHandle_t blink_task_ = nullptr;
|
||||
led_strip_handle_t led_strip_ = nullptr;
|
||||
uint8_t r_ = 0, g_ = 0, b_ = 0;
|
||||
int blink_counter_ = 0;
|
||||
int blink_interval_ms_ = 0;
|
||||
esp_timer_handle_t blink_timer_ = nullptr;
|
||||
|
||||
void StartBlinkTask(int times, int interval_ms);
|
||||
void OnBlinkTimer();
|
||||
|
||||
void BlinkOnce();
|
||||
void Blink(int times, int interval_ms);
|
||||
void StartContinuousBlink(int interval_ms);
|
||||
void TurnOn();
|
||||
void TurnOff();
|
||||
void SetColor(uint8_t r, uint8_t g, uint8_t b);
|
||||
};
|
||||
|
||||
#endif // _SINGLE_LED_H_
|
||||
Reference in New Issue
Block a user