diff --git a/main/Application.cc b/main/Application.cc index 8ba4d0db..97e1e456 100644 --- a/main/Application.cc +++ b/main/Application.cc @@ -17,7 +17,8 @@ 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 , ml307_at_modem_(CONFIG_ML307_TX_PIN, CONFIG_ML307_RX_PIN, 4096), http_(ml307_at_modem_), @@ -220,7 +221,7 @@ void Application::Start() { Application* app = (Application*)arg; app->AudioPlayTask(); vTaskDelete(NULL); - }, "play_audio", 4096 * 2, this, 5, NULL); + }, "play_audio", 4096 * 4, this, 5, NULL); #ifdef CONFIG_USE_AFE_SR wake_word_detect_.OnVadStateChange([this](bool speaking) { @@ -286,7 +287,7 @@ void Application::Start() { builtin_led.SetGreen(); builtin_led.BlinkOnce(); - button_.OnClick([this]() { + boot_button_.OnClick([this]() { Schedule([this]() { if (chat_state_ == kChatStateIdle) { 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) { Application* app = (Application*)arg; app->MainLoop(); diff --git a/main/Application.h b/main/Application.h index 6ad5d0f4..3a35e74e 100644 --- a/main/Application.h +++ b/main/Application.h @@ -84,7 +84,8 @@ private: Application(); ~Application(); - Button button_; + Button boot_button_; + Button volume_up_button_; AudioDevice audio_device_; #ifdef CONFIG_USE_AFE_SR WakeWordDetect wake_word_detect_; diff --git a/main/AudioDevice.cc b/main/AudioDevice.cc index 5f7fac7f..ea569f84 100644 --- a/main/AudioDevice.cc +++ b/main/AudioDevice.cc @@ -1,7 +1,7 @@ #include "AudioDevice.h" #include #include - +#include #define TAG "AudioDevice" AudioDevice::AudioDevice() { @@ -152,8 +152,12 @@ void AudioDevice::CreateSimplexChannels() { void AudioDevice::Write(const int16_t* data, int 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++) { - buffer[i] = int32_t(data[i]) << 15; + buffer[i] = int32_t(data[i]) * volume_factor; } 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_); +} diff --git a/main/AudioDevice.h b/main/AudioDevice.h index 84bbed55..e6acdb1e 100644 --- a/main/AudioDevice.h +++ b/main/AudioDevice.h @@ -17,15 +17,17 @@ public: void Start(int input_sample_rate, int output_sample_rate); void OnInputData(std::function callback); void OutputData(std::vector& data); + void SetOutputVolume(int volume); int input_sample_rate() const { return input_sample_rate_; } int output_sample_rate() const { return output_sample_rate_; } bool duplex() const { return duplex_; } - + int output_volume() const { return output_volume_; } private: bool duplex_ = false; int input_sample_rate_ = 0; int output_sample_rate_ = 0; + int output_volume_ = 80; i2s_chan_handle_t tx_handle_ = nullptr; i2s_chan_handle_t rx_handle_ = nullptr; diff --git a/main/Button.cc b/main/Button.cc index 5dcaf3c4..46ffd847 100644 --- a/main/Button.cc +++ b/main/Button.cc @@ -6,8 +6,8 @@ static const char* TAG = "Button"; Button::Button(gpio_num_t gpio_num) : gpio_num_(gpio_num) { button_config_t button_config = { .type = BUTTON_TYPE_GPIO, - .long_press_time = 3000, - .short_press_time = 100, + .long_press_time = 1000, + .short_press_time = 50, .gpio_button_config = { .gpio_num = gpio_num, .active_level = 0 diff --git a/main/Display.cc b/main/Display.cc index 6f141be7..6b0256ad 100644 --- a/main/Display.cc +++ b/main/Display.cc @@ -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_obj_set_width(label_, disp_->driver->hor_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); - lv_obj_set_style_outline_pad(label_, 0, 0); + + notification_ = lv_label_create(lv_disp_get_scr_act(disp_)); + 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(); } } Display::~Display() { - if (label_ != nullptr) { - lvgl_port_lock(0); - lv_obj_del(label_); - lvgl_port_unlock(); + if (notification_timer_ != nullptr) { + esp_timer_stop(notification_timer_); + esp_timer_delete(notification_timer_); } + lvgl_port_lock(0); + if (label_ != nullptr) { + lv_obj_del(label_); + lv_obj_del(notification_); + } + lvgl_port_unlock(); + if (disp_ != nullptr) { lvgl_port_deinit(); 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(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 diff --git a/main/Display.h b/main/Display.h index 308778b5..c57bc622 100644 --- a/main/Display.h +++ b/main/Display.h @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -14,6 +15,7 @@ public: ~Display(); void SetText(const std::string &text); + void ShowNotification(const std::string &text); private: int sda_pin_; @@ -25,6 +27,8 @@ private: esp_lcd_panel_handle_t panel_ = nullptr; lv_disp_t *disp_ = nullptr; lv_obj_t *label_ = nullptr; + lv_obj_t *notification_ = nullptr; + esp_timer_handle_t notification_timer_ = nullptr; std::string text_; }; diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 1597144f..2cf57753 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -80,6 +80,12 @@ config BOOT_BUTTON_GPIO help 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 bool "Use Espressif AFE SR" default y