forked from xiaozhi/xiaozhi-esp32
add volume up gpio button
This commit is contained in:
@@ -17,7 +17,8 @@
|
|||||||
|
|
||||||
|
|
||||||
Application::Application()
|
Application::Application()
|
||||||
: button_((gpio_num_t)CONFIG_BOOT_BUTTON_GPIO)
|
: boot_button_((gpio_num_t)CONFIG_BOOT_BUTTON_GPIO),
|
||||||
|
volume_up_button_((gpio_num_t)CONFIG_VOLUME_UP_BUTTON_GPIO)
|
||||||
#ifdef CONFIG_USE_ML307
|
#ifdef CONFIG_USE_ML307
|
||||||
, ml307_at_modem_(CONFIG_ML307_TX_PIN, CONFIG_ML307_RX_PIN, 4096),
|
, ml307_at_modem_(CONFIG_ML307_TX_PIN, CONFIG_ML307_RX_PIN, 4096),
|
||||||
http_(ml307_at_modem_),
|
http_(ml307_at_modem_),
|
||||||
@@ -220,7 +221,7 @@ void Application::Start() {
|
|||||||
Application* app = (Application*)arg;
|
Application* app = (Application*)arg;
|
||||||
app->AudioPlayTask();
|
app->AudioPlayTask();
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}, "play_audio", 4096 * 2, this, 5, NULL);
|
}, "play_audio", 4096 * 4, this, 5, NULL);
|
||||||
|
|
||||||
#ifdef CONFIG_USE_AFE_SR
|
#ifdef CONFIG_USE_AFE_SR
|
||||||
wake_word_detect_.OnVadStateChange([this](bool speaking) {
|
wake_word_detect_.OnVadStateChange([this](bool speaking) {
|
||||||
@@ -286,7 +287,7 @@ void Application::Start() {
|
|||||||
builtin_led.SetGreen();
|
builtin_led.SetGreen();
|
||||||
builtin_led.BlinkOnce();
|
builtin_led.BlinkOnce();
|
||||||
|
|
||||||
button_.OnClick([this]() {
|
boot_button_.OnClick([this]() {
|
||||||
Schedule([this]() {
|
Schedule([this]() {
|
||||||
if (chat_state_ == kChatStateIdle) {
|
if (chat_state_ == kChatStateIdle) {
|
||||||
SetChatState(kChatStateConnecting);
|
SetChatState(kChatStateConnecting);
|
||||||
@@ -312,6 +313,28 @@ void Application::Start() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
volume_up_button_.OnClick([this]() {
|
||||||
|
Schedule([this]() {
|
||||||
|
auto volume = audio_device_.output_volume() + 10;
|
||||||
|
if (volume > 100) {
|
||||||
|
volume = 0;
|
||||||
|
}
|
||||||
|
audio_device_.SetOutputVolume(volume);
|
||||||
|
#ifdef CONFIG_USE_DISPLAY
|
||||||
|
display_.ShowNotification("Volume\n" + std::to_string(volume));
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
volume_up_button_.OnLongPress([this]() {
|
||||||
|
Schedule([this]() {
|
||||||
|
audio_device_.SetOutputVolume(0);
|
||||||
|
#ifdef CONFIG_USE_DISPLAY
|
||||||
|
display_.ShowNotification("Volume\n0");
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
xTaskCreate([](void* arg) {
|
xTaskCreate([](void* arg) {
|
||||||
Application* app = (Application*)arg;
|
Application* app = (Application*)arg;
|
||||||
app->MainLoop();
|
app->MainLoop();
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ private:
|
|||||||
Application();
|
Application();
|
||||||
~Application();
|
~Application();
|
||||||
|
|
||||||
Button button_;
|
Button boot_button_;
|
||||||
|
Button volume_up_button_;
|
||||||
AudioDevice audio_device_;
|
AudioDevice audio_device_;
|
||||||
#ifdef CONFIG_USE_AFE_SR
|
#ifdef CONFIG_USE_AFE_SR
|
||||||
WakeWordDetect wake_word_detect_;
|
WakeWordDetect wake_word_detect_;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "AudioDevice.h"
|
#include "AudioDevice.h"
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
#define TAG "AudioDevice"
|
#define TAG "AudioDevice"
|
||||||
|
|
||||||
AudioDevice::AudioDevice() {
|
AudioDevice::AudioDevice() {
|
||||||
@@ -152,8 +152,12 @@ void AudioDevice::CreateSimplexChannels() {
|
|||||||
|
|
||||||
void AudioDevice::Write(const int16_t* data, int samples) {
|
void AudioDevice::Write(const int16_t* data, int samples) {
|
||||||
int32_t buffer[samples];
|
int32_t buffer[samples];
|
||||||
|
|
||||||
|
// output_volume_: 0-100
|
||||||
|
// volume_factor_: 0-65536
|
||||||
|
int32_t volume_factor = pow(double(output_volume_) / 100.0, 2) * 65536;
|
||||||
for (int i = 0; i < samples; i++) {
|
for (int i = 0; i < samples; i++) {
|
||||||
buffer[i] = int32_t(data[i]) << 15;
|
buffer[i] = int32_t(data[i]) * volume_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bytes_written;
|
size_t bytes_written;
|
||||||
@@ -196,3 +200,8 @@ void AudioDevice::InputTask() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioDevice::SetOutputVolume(int volume) {
|
||||||
|
output_volume_ = volume;
|
||||||
|
ESP_LOGI(TAG, "Set output volume to %d", output_volume_);
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,15 +17,17 @@ public:
|
|||||||
void Start(int input_sample_rate, int output_sample_rate);
|
void Start(int input_sample_rate, int output_sample_rate);
|
||||||
void OnInputData(std::function<void(const int16_t*, int)> callback);
|
void OnInputData(std::function<void(const int16_t*, int)> callback);
|
||||||
void OutputData(std::vector<int16_t>& data);
|
void OutputData(std::vector<int16_t>& data);
|
||||||
|
void SetOutputVolume(int volume);
|
||||||
|
|
||||||
int input_sample_rate() const { return input_sample_rate_; }
|
int input_sample_rate() const { return input_sample_rate_; }
|
||||||
int output_sample_rate() const { return output_sample_rate_; }
|
int output_sample_rate() const { return output_sample_rate_; }
|
||||||
bool duplex() const { return duplex_; }
|
bool duplex() const { return duplex_; }
|
||||||
|
int output_volume() const { return output_volume_; }
|
||||||
private:
|
private:
|
||||||
bool duplex_ = false;
|
bool duplex_ = false;
|
||||||
int input_sample_rate_ = 0;
|
int input_sample_rate_ = 0;
|
||||||
int output_sample_rate_ = 0;
|
int output_sample_rate_ = 0;
|
||||||
|
int output_volume_ = 80;
|
||||||
i2s_chan_handle_t tx_handle_ = nullptr;
|
i2s_chan_handle_t tx_handle_ = nullptr;
|
||||||
i2s_chan_handle_t rx_handle_ = nullptr;
|
i2s_chan_handle_t rx_handle_ = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ static const char* TAG = "Button";
|
|||||||
Button::Button(gpio_num_t gpio_num) : gpio_num_(gpio_num) {
|
Button::Button(gpio_num_t gpio_num) : gpio_num_(gpio_num) {
|
||||||
button_config_t button_config = {
|
button_config_t button_config = {
|
||||||
.type = BUTTON_TYPE_GPIO,
|
.type = BUTTON_TYPE_GPIO,
|
||||||
.long_press_time = 3000,
|
.long_press_time = 1000,
|
||||||
.short_press_time = 100,
|
.short_press_time = 50,
|
||||||
.gpio_button_config = {
|
.gpio_button_config = {
|
||||||
.gpio_num = gpio_num,
|
.gpio_num = gpio_num,
|
||||||
.active_level = 0
|
.active_level = 0
|
||||||
|
|||||||
@@ -104,20 +104,29 @@ Display::Display(int sda_pin, int scl_pin) : sda_pin_(sda_pin), scl_pin_(scl_pin
|
|||||||
lv_label_set_text(label_, "Initializing...");
|
lv_label_set_text(label_, "Initializing...");
|
||||||
lv_obj_set_width(label_, disp_->driver->hor_res);
|
lv_obj_set_width(label_, disp_->driver->hor_res);
|
||||||
lv_obj_set_height(label_, disp_->driver->ver_res);
|
lv_obj_set_height(label_, disp_->driver->ver_res);
|
||||||
lv_obj_set_style_text_line_space(label_, 0, 0);
|
|
||||||
lv_obj_set_style_pad_all(label_, 0, 0);
|
notification_ = lv_label_create(lv_disp_get_scr_act(disp_));
|
||||||
lv_obj_set_style_outline_pad(label_, 0, 0);
|
lv_label_set_text(notification_, "Notification\nTest");
|
||||||
|
lv_obj_set_width(notification_, disp_->driver->hor_res);
|
||||||
|
lv_obj_set_height(notification_, disp_->driver->ver_res);
|
||||||
|
lv_obj_set_style_opa(notification_, LV_OPA_MIN, 0);
|
||||||
lvgl_port_unlock();
|
lvgl_port_unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Display::~Display() {
|
Display::~Display() {
|
||||||
if (label_ != nullptr) {
|
if (notification_timer_ != nullptr) {
|
||||||
lvgl_port_lock(0);
|
esp_timer_stop(notification_timer_);
|
||||||
lv_obj_del(label_);
|
esp_timer_delete(notification_timer_);
|
||||||
lvgl_port_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lvgl_port_lock(0);
|
||||||
|
if (label_ != nullptr) {
|
||||||
|
lv_obj_del(label_);
|
||||||
|
lv_obj_del(notification_);
|
||||||
|
}
|
||||||
|
lvgl_port_unlock();
|
||||||
|
|
||||||
if (disp_ != nullptr) {
|
if (disp_ != nullptr) {
|
||||||
lvgl_port_deinit();
|
lvgl_port_deinit();
|
||||||
esp_lcd_panel_del(panel_);
|
esp_lcd_panel_del(panel_);
|
||||||
@@ -136,4 +145,35 @@ void Display::SetText(const std::string &text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Display::ShowNotification(const std::string &text) {
|
||||||
|
if (notification_ != nullptr) {
|
||||||
|
lvgl_port_lock(0);
|
||||||
|
lv_label_set_text(notification_, text.c_str());
|
||||||
|
lv_obj_set_style_opa(notification_, LV_OPA_MAX, 0);
|
||||||
|
lv_obj_set_style_opa(label_, LV_OPA_MIN, 0);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
|
||||||
|
if (notification_timer_ != nullptr) {
|
||||||
|
esp_timer_stop(notification_timer_);
|
||||||
|
esp_timer_delete(notification_timer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_timer_create_args_t timer_args = {
|
||||||
|
.callback = [](void *arg) {
|
||||||
|
Display *display = static_cast<Display*>(arg);
|
||||||
|
lvgl_port_lock(0);
|
||||||
|
lv_obj_set_style_opa(display->notification_, LV_OPA_MIN, 0);
|
||||||
|
lv_obj_set_style_opa(display->label_, LV_OPA_MAX, 0);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
},
|
||||||
|
.arg = this,
|
||||||
|
.dispatch_method = ESP_TIMER_TASK,
|
||||||
|
.name = "Notification Timer",
|
||||||
|
.skip_unhandled_events = false,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_timer_create(&timer_args, ¬ification_timer_));
|
||||||
|
ESP_ERROR_CHECK(esp_timer_start_once(notification_timer_, 3000000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <esp_lcd_panel_io.h>
|
#include <esp_lcd_panel_io.h>
|
||||||
#include <esp_lcd_panel_ops.h>
|
#include <esp_lcd_panel_ops.h>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
#include <esp_timer.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ public:
|
|||||||
~Display();
|
~Display();
|
||||||
|
|
||||||
void SetText(const std::string &text);
|
void SetText(const std::string &text);
|
||||||
|
void ShowNotification(const std::string &text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int sda_pin_;
|
int sda_pin_;
|
||||||
@@ -25,6 +27,8 @@ private:
|
|||||||
esp_lcd_panel_handle_t panel_ = nullptr;
|
esp_lcd_panel_handle_t panel_ = nullptr;
|
||||||
lv_disp_t *disp_ = nullptr;
|
lv_disp_t *disp_ = nullptr;
|
||||||
lv_obj_t *label_ = nullptr;
|
lv_obj_t *label_ = nullptr;
|
||||||
|
lv_obj_t *notification_ = nullptr;
|
||||||
|
esp_timer_handle_t notification_timer_ = nullptr;
|
||||||
|
|
||||||
std::string text_;
|
std::string text_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -80,6 +80,12 @@ config BOOT_BUTTON_GPIO
|
|||||||
help
|
help
|
||||||
GPIO number of the boot button.
|
GPIO number of the boot button.
|
||||||
|
|
||||||
|
config VOLUME_UP_BUTTON_GPIO
|
||||||
|
int "Volume Up Button GPIO"
|
||||||
|
default 40
|
||||||
|
help
|
||||||
|
GPIO number of the volume up button.
|
||||||
|
|
||||||
config USE_AFE_SR
|
config USE_AFE_SR
|
||||||
bool "Use Espressif AFE SR"
|
bool "Use Espressif AFE SR"
|
||||||
default y
|
default y
|
||||||
|
|||||||
Reference in New Issue
Block a user