forked from xiaozhi/xiaozhi-esp32
Support adjust volume with knob in SenseCAP Watcher (#399)
* fix typo, add missing prefix `CONFIG` to `ESP_TASK_WDT_TIMEOUT_S` * add KNOB gpio spec to sensecap config * create new knob component * implement ajust output volume with knob * modify function name to UpperCamelCase * Tidy up comments and logs
This commit is contained in:
52
main/boards/common/knob.cc
Normal file
52
main/boards/common/knob.cc
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "knob.h"
|
||||
|
||||
static const char* TAG = "Knob";
|
||||
|
||||
Knob::Knob(gpio_num_t pin_a, gpio_num_t pin_b) {
|
||||
knob_config_t config = {
|
||||
.default_direction = 0,
|
||||
.gpio_encoder_a = static_cast<uint8_t>(pin_a),
|
||||
.gpio_encoder_b = static_cast<uint8_t>(pin_b),
|
||||
};
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
knob_handle_ = iot_knob_create(&config);
|
||||
if (knob_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create knob instance");
|
||||
return;
|
||||
}
|
||||
|
||||
err = iot_knob_register_cb(knob_handle_, KNOB_LEFT, knob_callback, this);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register left callback: %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
err = iot_knob_register_cb(knob_handle_, KNOB_RIGHT, knob_callback, this);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register right callback: %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Knob initialized with pins A:%d B:%d", pin_a, pin_b);
|
||||
}
|
||||
|
||||
Knob::~Knob() {
|
||||
if (knob_handle_ != NULL) {
|
||||
iot_knob_delete(knob_handle_);
|
||||
knob_handle_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Knob::OnRotate(std::function<void(bool)> callback) {
|
||||
on_rotate_ = callback;
|
||||
}
|
||||
|
||||
void Knob::knob_callback(void* arg, void* data) {
|
||||
Knob* knob = static_cast<Knob*>(data);
|
||||
knob_event_t event = iot_knob_get_event(arg);
|
||||
|
||||
if (knob->on_rotate_) {
|
||||
knob->on_rotate_(event == KNOB_RIGHT);
|
||||
}
|
||||
}
|
||||
25
main/boards/common/knob.h
Normal file
25
main/boards/common/knob.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef KNOB_H_
|
||||
#define KNOB_H_
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <functional>
|
||||
#include <esp_log.h>
|
||||
#include <iot_knob.h>
|
||||
|
||||
class Knob {
|
||||
public:
|
||||
Knob(gpio_num_t pin_a, gpio_num_t pin_b);
|
||||
~Knob();
|
||||
|
||||
void OnRotate(std::function<void(bool)> callback);
|
||||
|
||||
private:
|
||||
static void knob_callback(void* arg, void* data);
|
||||
|
||||
knob_handle_t knob_handle_;
|
||||
gpio_num_t pin_a_;
|
||||
gpio_num_t pin_b_;
|
||||
std::function<void(bool)> on_rotate_;
|
||||
};
|
||||
|
||||
#endif // KNOB_H_
|
||||
@@ -114,7 +114,7 @@ private:
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO));
|
||||
}
|
||||
|
||||
void Initializespd2010Display() {
|
||||
void InitializeSpd2010Display() {
|
||||
esp_lcd_panel_io_handle_t panel_io = nullptr;
|
||||
esp_lcd_panel_handle_t panel = nullptr;
|
||||
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
InitializeI2c();
|
||||
InitializeTca9554();
|
||||
InitializeSpi();
|
||||
Initializespd2010Display();
|
||||
InitializeSpd2010Display();
|
||||
InitializeButtons();
|
||||
InitializeIot();
|
||||
GetBacklight()->RestoreBrightness();
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
#define BSP_PWR_START_UP (BSP_PWR_SDCARD | BSP_PWR_LCD | BSP_PWR_SYSTEM | BSP_PWR_AI_CHIP | BSP_PWR_CODEC_PA | BSP_PWR_GROVE | BSP_PWR_BAT_ADC)
|
||||
|
||||
#define BSP_KNOB_BTN (IO_EXPANDER_PIN_NUM_3)
|
||||
|
||||
#define BSP_KNOB_A_PIN GPIO_NUM_41
|
||||
#define BSP_KNOB_B_PIN GPIO_NUM_42
|
||||
|
||||
/* QSPI */
|
||||
#define BSP_SPI3_HOST_PCLK (GPIO_NUM_7)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "font_awesome_symbols.h"
|
||||
#include "application.h"
|
||||
#include "button.h"
|
||||
#include "knob.h"
|
||||
#include "config.h"
|
||||
#include "led/single_led.h"
|
||||
#include "iot/thing_manager.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include <driver/spi_common.h>
|
||||
#include <wifi_station.h>
|
||||
#include <iot_button.h>
|
||||
#include <iot_knob.h>
|
||||
#include <esp_io_expander_tca95xx_16bit.h>
|
||||
#include <esp_sleep.h>
|
||||
|
||||
@@ -34,6 +36,7 @@ class SensecapWatcher : public WifiBoard {
|
||||
private:
|
||||
i2c_master_bus_handle_t i2c_bus_;
|
||||
LcdDisplay* display_;
|
||||
std::unique_ptr<Knob> knob_;
|
||||
esp_io_expander_handle_t io_exp_handle;
|
||||
button_handle_t btns;
|
||||
PowerSaveTimer* power_save_timer_;
|
||||
@@ -115,6 +118,41 @@ private:
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
void OnKnobRotate(bool clockwise) {
|
||||
auto codec = GetAudioCodec();
|
||||
int current_volume = codec->output_volume();
|
||||
int new_volume = current_volume + (clockwise ? 5 : -5);
|
||||
|
||||
// 确保音量在有效范围内
|
||||
if (new_volume > 100) {
|
||||
new_volume = 100;
|
||||
ESP_LOGW(TAG, "Volume reached maximum limit: %d", new_volume);
|
||||
} else if (new_volume < 0) {
|
||||
new_volume = 0;
|
||||
ESP_LOGW(TAG, "Volume reached minimum limit: %d", new_volume);
|
||||
}
|
||||
|
||||
codec->SetOutputVolume(new_volume);
|
||||
ESP_LOGI(TAG, "Volume changed from %d to %d", current_volume, new_volume);
|
||||
|
||||
// 显示通知前检查实际变化
|
||||
if (new_volume != codec->output_volume()) {
|
||||
ESP_LOGE(TAG, "Failed to set volume! Expected:%d Actual:%d",
|
||||
new_volume, codec->output_volume());
|
||||
}
|
||||
GetDisplay()->ShowNotification("音量: " + std::to_string(codec->output_volume()));
|
||||
power_save_timer_->WakeUp();
|
||||
}
|
||||
|
||||
void InitializeKnob() {
|
||||
knob_ = std::make_unique<Knob>(BSP_KNOB_A_PIN, BSP_KNOB_B_PIN);
|
||||
knob_->OnRotate([this](bool clockwise) {
|
||||
ESP_LOGD(TAG, "Knob rotation detected. Clockwise:%s", clockwise ? "true" : "false");
|
||||
OnKnobRotate(clockwise);
|
||||
});
|
||||
ESP_LOGI(TAG, "Knob initialized with pins A:%d B:%d", BSP_KNOB_A_PIN, BSP_KNOB_B_PIN);
|
||||
}
|
||||
|
||||
void InitializeButton() {
|
||||
button_config_t btn_config = {
|
||||
.type = BUTTON_TYPE_CUSTOM,
|
||||
@@ -250,6 +288,7 @@ public:
|
||||
InitializeSpi();
|
||||
InitializeExpander();
|
||||
InitializeButton();
|
||||
InitializeKnob();
|
||||
Initializespd2010Display();
|
||||
InitializeIot();
|
||||
GetBacklight()->RestoreBrightness();
|
||||
|
||||
Reference in New Issue
Block a user