Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,13 @@ choice DISPLAY_OLED_TYPE
bool "SH1106 128*64"
endchoice

config OLED_AUTO_POWER_SAVE
bool "Enable OLED Auto Power Save"
depends on BOARD_TYPE_BREAD_COMPACT_WIFI
help
Automatically turn off the OLED display after a period of inactivity.
The screen wakes up on button press or voice activity.

choice DISPLAY_LCD_TYPE
depends on BOARD_TYPE_BREAD_COMPACT_WIFI_LCD || BOARD_TYPE_BREAD_COMPACT_ESP32_LCD || BOARD_TYPE_CGC || BOARD_TYPE_WAVESHARE_P4_NANO || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC || BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
prompt "LCD Type"
Expand Down
57 changes: 57 additions & 0 deletions main/boards/bread-compact-wifi/compact_wifi_board.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include "lamp_controller.h"
#include "led/single_led.h"
#include "assets/lang_config.h"
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
#include "power_save_timer.h"
#endif

#include <esp_log.h>
#include <driver/i2c_master.h>
Expand All @@ -21,6 +24,8 @@

#define TAG "CompactWifiBoard"

static constexpr int kPowerSaveTimeoutSeconds = 60;

class CompactWifiBoard : public WifiBoard {
private:
i2c_master_bus_handle_t display_i2c_bus_;
Expand All @@ -31,6 +36,20 @@ class CompactWifiBoard : public WifiBoard {
Button touch_button_;
Button volume_up_button_;
Button volume_down_button_;
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
PowerSaveTimer* power_save_timer_;

void InitializePowerSaveTimer() {
power_save_timer_ = new PowerSaveTimer(-1, kPowerSaveTimeoutSeconds, -1);
power_save_timer_->OnEnterSleepMode([this]() {
GetDisplay()->SetPowerSaveMode(true);
});
power_save_timer_->OnExitSleepMode([this]() {
GetDisplay()->SetPowerSaveMode(false);
});
power_save_timer_->SetEnabled(true);
}
#endif

void InitializeDisplayI2c() {
i2c_master_bus_config_t bus_config = {
Expand Down Expand Up @@ -102,6 +121,9 @@ class CompactWifiBoard : public WifiBoard {

void InitializeButtons() {
boot_button_.OnClick([this]() {
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
power_save_timer_->WakeUp();
#endif
auto& app = Application::GetInstance();
if (app.GetDeviceState() == kDeviceStateStarting) {
EnterWifiConfigMode();
Expand All @@ -110,13 +132,22 @@ class CompactWifiBoard : public WifiBoard {
app.ToggleChatState();
});
touch_button_.OnPressDown([this]() {
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
power_save_timer_->WakeUp();
#endif
Application::GetInstance().StartListening();
});
touch_button_.OnPressUp([this]() {
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
power_save_timer_->WakeUp();
#endif
Application::GetInstance().StopListening();
});

volume_up_button_.OnClick([this]() {
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
power_save_timer_->WakeUp();
#endif
auto codec = GetAudioCodec();
auto volume = codec->output_volume() + 10;
if (volume > 100) {
Expand All @@ -127,11 +158,17 @@ class CompactWifiBoard : public WifiBoard {
});

volume_up_button_.OnLongPress([this]() {
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
power_save_timer_->WakeUp();
#endif
GetAudioCodec()->SetOutputVolume(100);
GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME);
});

volume_down_button_.OnClick([this]() {
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
power_save_timer_->WakeUp();
#endif
auto codec = GetAudioCodec();
auto volume = codec->output_volume() - 10;
if (volume < 0) {
Expand All @@ -142,6 +179,9 @@ class CompactWifiBoard : public WifiBoard {
});

volume_down_button_.OnLongPress([this]() {
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
power_save_timer_->WakeUp();
#endif
GetAudioCodec()->SetOutputVolume(0);
GetDisplay()->ShowNotification(Lang::Strings::MUTED);
});
Expand All @@ -160,6 +200,9 @@ class CompactWifiBoard : public WifiBoard {
volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) {
InitializeDisplayI2c();
InitializeSsd1306Display();
#ifdef CONFIG_OLED_AUTO_POWER_SAVE
InitializePowerSaveTimer();
#endif
InitializeButtons();
InitializeTools();
}
Expand All @@ -183,6 +226,20 @@ class CompactWifiBoard : public WifiBoard {
virtual Display* GetDisplay() override {
return display_;
}

virtual Backlight* GetBacklight() override {
static OledBacklight backlight(static_cast<OledDisplay*>(display_));
return &backlight;
}

#ifdef CONFIG_OLED_AUTO_POWER_SAVE
virtual void SetPowerSaveLevel(PowerSaveLevel level) override {
if (level != PowerSaveLevel::LOW_POWER) {
power_save_timer_->WakeUp();
}
WifiBoard::SetPowerSaveLevel(level);
}
#endif
};

DECLARE_BOARD(CompactWifiBoard);
2 changes: 1 addition & 1 deletion main/boards/common/backlight.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Backlight {
~Backlight();

void RestoreBrightness();
void SetBrightness(uint8_t brightness, bool permanent = false);
virtual void SetBrightness(uint8_t brightness, bool permanent = false);
inline uint8_t brightness() const { return brightness_; }

protected:
Expand Down
50 changes: 50 additions & 0 deletions main/display/oled_display.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "oled_display.h"
#include "settings.h"
#include "assets/lang_config.h"
#include "lvgl_theme.h"
#include "lvgl_font.h"
Expand Down Expand Up @@ -394,3 +395,52 @@ void OledDisplay::SetTheme(Theme* theme) {
auto screen = lv_screen_active();
lv_obj_set_style_text_font(screen, text_font, 0);
}

void OledDisplay::SetPowerSaveMode(bool on) {
LvglDisplay::SetPowerSaveMode(on);
if (panel_ != nullptr) {
esp_lcd_panel_disp_on_off(panel_, !on);
}
}

void OledDisplay::SetContrast(uint8_t contrast) {
if (panel_io_ != nullptr) {
ESP_LOGI(TAG, "SetContrast: %d", contrast);
esp_lcd_panel_io_tx_param(panel_io_, 0x81, &contrast, 1);
}
}

OledBacklight::OledBacklight(OledDisplay* display) : display_(display) {
brightness_ = 50;
}

void OledBacklight::SetBrightness(uint8_t brightness, bool permanent) {
if (brightness > 100) {
brightness = 100;
}
if (brightness_ == brightness) {
return;
}

if (permanent) {
Settings settings("display", true);
settings.SetInt("brightness", brightness);
}

brightness_ = brightness;
target_brightness_ = brightness;
SetBrightnessImpl(brightness);
ESP_LOGI(TAG, "Set OLED brightness to %d", brightness);
}

void OledBacklight::SetBrightnessImpl(uint8_t brightness) {
if (brightness <= 5) {
display_->SetPowerSaveMode(true);
} else {
display_->SetPowerSaveMode(false);
// Map 6-100 to 0-255
// 5 is min brightness, so we map 5-100 to 0-255 roughly
uint8_t contrast = static_cast<uint8_t>((brightness) * 255 / 100);
display_->SetContrast(contrast);
}
}
13 changes: 13 additions & 0 deletions main/display/oled_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define OLED_DISPLAY_H

#include "lvgl_display.h"
#include "backlight.h"

#include <esp_lcd_panel_io.h>
#include <esp_lcd_panel_ops.h>
Expand Down Expand Up @@ -35,6 +36,18 @@ class OledDisplay : public LvglDisplay {
virtual void SetChatMessage(const char* role, const char* content) override;
virtual void SetEmotion(const char* emotion) override;
virtual void SetTheme(Theme* theme) override;
virtual void SetPowerSaveMode(bool on) override;
void SetContrast(uint8_t contrast);
};

class OledBacklight : public Backlight {
public:
OledBacklight(OledDisplay* display);
void SetBrightness(uint8_t brightness, bool permanent = false) override;
void SetBrightnessImpl(uint8_t brightness) override;

private:
OledDisplay* display_;
};

#endif // OLED_DISPLAY_H