Initial commit

This commit is contained in:
2026-04-26 21:35:04 +08:00
commit da6ca1b09a
1483 changed files with 115719 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
# 产品链接
[微雪电子 ESP32-S3-ePaper-3.97](https://www.waveshare.net/shop/ESP32-S3-ePaper-3.97.htm)
# 编译配置命令
**克隆工程**
```bash
git clone https://github.com/78/xiaozhi-esp32.git
```
**进入工程**
```bash
cd xiaozhi-esp32
```
**配置编译目标为 ESP32S3**
```bash
idf.py set-target esp32s3
```
**打开 menuconfig**
```bash
idf.py menuconfig
```
**选择板子**
```bash
Xiaozhi Assistant -> Board Type -> Waveshare ESP32-S3-ePaper-3.97
```
**编译**
```ba
idf.py build
```
**下载并打开串口终端**
```bash
idf.py build flash monitor
```

View File

@@ -0,0 +1,44 @@
#ifndef _BOARD_CONFIG_H_
#define _BOARD_CONFIG_H_
#include <driver/gpio.h>
#define AUDIO_INPUT_SAMPLE_RATE 24000
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13
#define AUDIO_I2S_GPIO_WS GPIO_NUM_47
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_14
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_21
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_48
#define AUDIO_CODEC_PA_PIN GPIO_NUM_39
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_41
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_42
#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR
#define BOOT_BUTTON_GPIO GPIO_NUM_0
#define VBAT_PWR_GPIO GPIO_NUM_1
#define EPD_SPI_NUM SPI3_HOST
#define EPD_DC_PIN GPIO_NUM_9
#define EPD_CS_PIN GPIO_NUM_10
#define EPD_SCK_PIN GPIO_NUM_11
#define EPD_MOSI_PIN GPIO_NUM_12
#define EPD_RST_PIN GPIO_NUM_46
#define EPD_BUSY_PIN GPIO_NUM_3
#define EXAMPLE_LCD_WIDTH 800
#define EXAMPLE_LCD_HEIGHT 480
#define DISPLAY_MIRROR_X false
#define DISPLAY_MIRROR_Y false
#define DISPLAY_SWAP_XY false
#define DISPLAY_OFFSET_X 0
#define DISPLAY_OFFSET_Y 0
#endif // _BOARD_CONFIG_H_

View File

@@ -0,0 +1,12 @@
{
"manufacturer": "waveshare",
"target": "esp32s3",
"builds": [
{
"name": "esp32-s3-epaper-3.97",
"sdkconfig_append": [
"CONFIG_USE_WECHAT_MESSAGE_STYLE=n"
]
}
]
}

View File

@@ -0,0 +1,393 @@
#include "custom_lcd_display.h"
#include <esp_lcd_panel_io.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <stdio.h>
#include <vector>
#include "board.h"
#include "config.h"
#include "esp_lvgl_port.h"
#include "settings.h"
#define TAG "CustomEpdDisplay"
#define BYTES_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565))
#define BUFF_SIZE (EXAMPLE_LCD_WIDTH * EXAMPLE_LCD_HEIGHT * BYTES_PER_PIXEL)
void CustomEpdDisplay::lvgl_flush_cb(lv_display_t* disp, const lv_area_t* area, uint8_t* color_p) {
assert(disp != NULL);
CustomEpdDisplay* driver = (CustomEpdDisplay*)lv_display_get_user_data(disp);
uint16_t* buffer = (uint16_t*)color_p;
driver->EPD_Clear();
for (int y = area->y1; y <= area->y2; y++) {
for (int x = area->x1; x <= area->x2; x++) {
uint8_t color = (*buffer < 0x7fff) ? DRIVER_COLOR_BLACK : DRIVER_COLOR_WHITE;
driver->EPD_DrawColorPixel(x, y, color);
buffer++;
}
}
driver->EPD_DisplayPart();
lv_disp_flush_ready(disp);
}
CustomEpdDisplay::CustomEpdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel,
int width, int height, int offset_x, int offset_y, bool mirror_x,
bool mirror_y, bool swap_xy, custom_epd_spi_t _epd_spi_data)
: LcdDisplay(panel_io, panel, width, height),
epd_spi_data(_epd_spi_data),
Width(width),
Height(height) {
ESP_LOGI(TAG, "Initialize SPI");
spi_port_init();
spi_gpio_init();
ESP_LOGI(TAG, "Initialize LVGL library");
lv_init();
lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG();
port_cfg.task_priority = 2;
port_cfg.timer_period_ms = 50;
lvgl_port_init(&port_cfg);
lvgl_port_lock(0);
buffer = (uint8_t*)heap_caps_malloc(epd_spi_data.buffer_len, MALLOC_CAP_SPIRAM);
assert(buffer);
display_ = lv_display_create(width, height); /* 以水平和垂直分辨率(像素)进行基本初始化 */
lv_display_set_flush_cb(display_, lvgl_flush_cb);
lv_display_set_user_data(display_, this);
uint8_t* buffer_1 = NULL;
buffer_1 = (uint8_t*)heap_caps_malloc(BUFF_SIZE, MALLOC_CAP_SPIRAM);
assert(buffer_1);
lv_display_set_buffers(display_, buffer_1, NULL, BUFF_SIZE, LV_DISPLAY_RENDER_MODE_FULL);
ESP_LOGI(TAG, "EPD init");
EPD_Init();
ESP_LOGI(TAG, "EPD Clear");
EPD_Clear();
EPD_Display();
lvgl_port_unlock();
if (display_ == nullptr) {
ESP_LOGE(TAG, "Failed to add display");
return;
}
ESP_LOGI(TAG, "ui start");
SetupUI();
}
CustomEpdDisplay::~CustomEpdDisplay() {}
void CustomEpdDisplay::spi_gpio_init() {
int rst = epd_spi_data.rst;
int cs = epd_spi_data.cs;
int dc = epd_spi_data.dc;
int busy = epd_spi_data.busy;
gpio_config_t gpio_conf = {};
gpio_conf.intr_type = GPIO_INTR_DISABLE;
gpio_conf.mode = GPIO_MODE_OUTPUT;
gpio_conf.pin_bit_mask = (0x1ULL << rst) | (0x1ULL << dc) | (0x1ULL << cs);
gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE;
ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf));
gpio_conf.mode = GPIO_MODE_INPUT;
gpio_conf.pin_bit_mask = (0x1ULL << busy);
ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf));
set_rst_1();
}
void CustomEpdDisplay::spi_port_init() {
int mosi = epd_spi_data.mosi;
int scl = epd_spi_data.scl;
int spi_host = epd_spi_data.spi_host;
esp_err_t ret;
spi_bus_config_t buscfg = {};
buscfg.miso_io_num = -1;
buscfg.mosi_io_num = mosi;
buscfg.sclk_io_num = scl;
buscfg.quadwp_io_num = -1;
buscfg.quadhd_io_num = -1;
buscfg.max_transfer_sz = 4096;
spi_device_interface_config_t devcfg = {};
devcfg.spics_io_num = -1;
devcfg.clock_speed_hz = 20 * 1000 * 1000; // Clock out at 10 MHz
devcfg.mode = 0; // SPI mode 0
devcfg.queue_size = 7; // We want to be able to queue 7 transactions at a time
ret = spi_bus_initialize((spi_host_device_t)spi_host, &buscfg, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
ret = spi_bus_add_device((spi_host_device_t)spi_host, &devcfg, &spi);
ESP_ERROR_CHECK(ret);
}
void CustomEpdDisplay::read_busy() {
int busy = epd_spi_data.busy;
while (gpio_get_level((gpio_num_t)busy) == 1) {
vTaskDelay(pdMS_TO_TICKS(5)); // LOW: idle, HIGH: busy
}
}
void CustomEpdDisplay::SPI_SendByte(uint8_t data) {
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = 8;
t.tx_buffer = &data;
ret = spi_device_polling_transmit(spi, &t); // Transmit!
assert(ret == ESP_OK); // Should have had no issues.
}
void CustomEpdDisplay::EPD_SendData(uint8_t data) {
set_dc_1();
set_cs_0();
SPI_SendByte(data);
set_cs_1();
}
void CustomEpdDisplay::EPD_SendCommand(uint8_t command) {
set_dc_0();
set_cs_0();
SPI_SendByte(command);
set_cs_1();
}
void CustomEpdDisplay::writeBytes(uint8_t* buffer, int len) {
set_dc_1();
set_cs_0();
const int MAX_SPI_TRANSFER = 4096;
int remaining = len;
int offset = 0;
while (remaining > 0) {
int chunk_size = (remaining > MAX_SPI_TRANSFER) ? MAX_SPI_TRANSFER : remaining;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = 8 * chunk_size;
t.tx_buffer = buffer + offset;
ret = spi_device_polling_transmit(spi, &t); // Transmit!
if (ret != ESP_OK) {
ESP_LOGE(TAG, "SPI transmit failed at offset %d, chunk %d: %s", offset, chunk_size,
esp_err_to_name(ret));
break;
}
remaining -= chunk_size;
offset += chunk_size;
}
set_cs_1();
}
void CustomEpdDisplay::writeBytes(const uint8_t* buffer, int len) {
set_dc_1();
set_cs_0();
const int MAX_SPI_TRANSFER = 4096;
int remaining = len;
int offset = 0;
while (remaining > 0) {
int chunk_size = (remaining > MAX_SPI_TRANSFER) ? MAX_SPI_TRANSFER : remaining;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = 8 * chunk_size;
t.tx_buffer = buffer + offset;
ret = spi_device_polling_transmit(spi, &t); // Transmit!
if (ret != ESP_OK) {
ESP_LOGE(TAG, "SPI transmit failed at offset %d, chunk %d: %s", offset, chunk_size,
esp_err_to_name(ret));
break;
}
remaining -= chunk_size;
offset += chunk_size;
}
set_cs_1();
}
void CustomEpdDisplay::EPD_SetWindows(uint16_t Xstart, uint16_t Ystart, uint16_t Xend,
uint16_t Yend) {
EPD_SendCommand(0x44); // SET_RAM_X_ADDRESS_START_END_POSITION
EPD_SendData((Xstart * 8) & 0xFF);
EPD_SendData(((Xstart * 8) >> 8) & 0xFF);
EPD_SendData((Xend * 8) & 0xFF);
EPD_SendData(((Xend * 8) >> 8) & 0xFF);
EPD_SendCommand(0x45); // SET_RAM_Y_ADDRESS_START_END_POSITION
EPD_SendData(Yend & 0xFF);
EPD_SendData((Yend >> 8) & 0xFF);
EPD_SendData(Ystart & 0xFF);
EPD_SendData((Ystart >> 8) & 0xFF);
}
void CustomEpdDisplay::EPD_SetCursor(uint16_t Xstart, uint16_t Ystart) {
EPD_SendCommand(0x4E);
EPD_SendData((Xstart * 8) & 0xFF);
EPD_SendData(((Xstart * 8) >> 8) & 0xFF);
EPD_SendCommand(0x4F);
EPD_SendData(Ystart & 0xFF);
EPD_SendData((Ystart >> 8) & 0xFF);
}
void CustomEpdDisplay::EPD_TurnOnDisplay() {
EPD_SendCommand(0x22);
EPD_SendData(0xF7);
EPD_SendCommand(0x20);
read_busy();
}
void CustomEpdDisplay::EPD_TurnOnDisplayPart() {
EPD_SendCommand(0x22);
EPD_SendData(0xFF);
EPD_SendCommand(0x20);
read_busy();
}
void CustomEpdDisplay::EPD_Init() {
set_rst_1();
vTaskDelay(pdMS_TO_TICKS(50));
set_rst_0();
vTaskDelay(pdMS_TO_TICKS(2));
set_rst_1();
vTaskDelay(pdMS_TO_TICKS(50));
read_busy();
EPD_SendCommand(0x12); // SWRESET
read_busy();
EPD_SendCommand(0x18);
EPD_SendData(0x80);
EPD_SendCommand(0x0C); // Driver output control
EPD_SendData(0xAE);
EPD_SendData(0xC7);
EPD_SendData(0xC3);
EPD_SendData(0xC0);
EPD_SendData(0x80);
EPD_SendCommand(0x01); // Driver output control
EPD_SendData((Height - 1) % 256);
EPD_SendData((Height - 1) / 256);
EPD_SendData(0x02);
EPD_SendCommand(0x3C); // BorderWavefrom
EPD_SendData(0x01);
EPD_SendCommand(0x11); // data entry mode
EPD_SendData(0x01);
EPD_SendCommand(0x44); // set Ram-X address start/end position
EPD_SendData(0x00);
EPD_SendData(0x00);
EPD_SendData((Width - 1) % 256);
EPD_SendData((Width - 1) / 256);
EPD_SendCommand(0x45); // set Ram-Y address start/end position
EPD_SendData((Height - 1) % 256);
EPD_SendData((Height - 1) / 256);
EPD_SendData(0x00);
EPD_SendData(0x00);
EPD_SendCommand(0x4E); // set RAM x address count to 0;
EPD_SendData(0x00);
EPD_SendData(0x00);
EPD_SendCommand(0x4F); // set RAM y address count to 0X199;
EPD_SendData(0x00);
EPD_SendData(0x00);
read_busy();
}
void CustomEpdDisplay::EPD_Clear() {
int buffer_len = epd_spi_data.buffer_len;
memset(buffer, 0xff, buffer_len);
}
void CustomEpdDisplay::EPD_Display() {
int buffer_len = epd_spi_data.buffer_len;
EPD_SendCommand(0x24);
assert(buffer);
writeBytes(buffer, buffer_len);
EPD_TurnOnDisplay();
}
void CustomEpdDisplay::EPD_DisplayPartBaseImage() {
int buffer_len = epd_spi_data.buffer_len;
EPD_SendCommand(0x24);
assert(buffer);
writeBytes(buffer, buffer_len);
EPD_SendCommand(0x26);
writeBytes(buffer, buffer_len);
EPD_TurnOnDisplay();
}
void CustomEpdDisplay::EPD_Init_Partial() {
set_rst_1();
vTaskDelay(pdMS_TO_TICKS(50));
set_rst_0();
vTaskDelay(pdMS_TO_TICKS(2));
set_rst_1();
vTaskDelay(pdMS_TO_TICKS(50));
read_busy();
EPD_SendCommand(0x18);
EPD_SendData(0x80);
EPD_SendCommand(0x3C);
EPD_SendData(0x80);
EPD_SetWindows(0, Width - 1, Height - 1, 0);
EPD_SetCursor(0, Height - 1);
read_busy();
}
void CustomEpdDisplay::EPD_DisplayPart() {
EPD_SendCommand(0x24);
assert(buffer);
writeBytes(buffer, 48000);
EPD_TurnOnDisplayPart();
}
void CustomEpdDisplay::EPD_Sleep() {
EPD_SendCommand(0x10); // enter deep sleep
EPD_SendData(0x01);
vTaskDelay(pdMS_TO_TICKS(10));
set_rst_0();
set_cs_0();
set_dc_0();
}
void CustomEpdDisplay::EPD_DrawColorPixel(uint16_t x, uint16_t y, uint8_t color) {
if (x >= Width || y >= Height) {
ESP_LOGE("EPD", "Out of bounds pixel: (%d,%d)", x, y);
return;
}
uint16_t index = y * Width / 8 + (x >> 3);
uint8_t bit = 7 - (x & 0x07);
if (color == DRIVER_COLOR_WHITE) {
buffer[index] |= (0x01 << bit);
} else {
buffer[index] &= ~(0x01 << bit);
}
}

View File

@@ -0,0 +1,74 @@
#ifndef __CUSTOM_LCD_DISPLAY_H__
#define __CUSTOM_LCD_DISPLAY_H__
#include <driver/gpio.h>
#include "lcd_display.h"
/* Display color */
typedef enum {
DRIVER_COLOR_WHITE = 0xff,
DRIVER_COLOR_BLACK = 0x00,
FONT_BACKGROUND = DRIVER_COLOR_WHITE,
} COLOR_IMAGE;
typedef struct {
uint8_t cs;
uint8_t dc;
uint8_t rst;
uint8_t busy;
uint8_t mosi;
uint8_t scl;
int spi_host;
int buffer_len;
} custom_epd_spi_t;
class CustomEpdDisplay : public LcdDisplay {
public:
CustomEpdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width,
int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y,
bool swap_xy, custom_epd_spi_t _epd_spi_data);
~CustomEpdDisplay();
void EPD_Init(); /* 墨水屏初始化 */
void EPD_Clear(); /* 清空屏幕 */
void EPD_Display(); /* 刷buffer到墨水屏 */
void EPD_Sleep();
/*快速刷新*/
void EPD_DisplayPartBaseImage();
void EPD_Init_Partial();
void EPD_DisplayPart();
void EPD_DrawColorPixel(uint16_t x, uint16_t y, uint8_t color);
private:
const custom_epd_spi_t epd_spi_data;
const int Width;
const int Height;
spi_device_handle_t spi;
uint8_t* buffer = NULL;
static void lvgl_flush_cb(lv_display_t* disp, const lv_area_t* area, uint8_t* color_p);
void spi_gpio_init();
void spi_port_init();
void read_busy();
void set_cs_1() { gpio_set_level((gpio_num_t)epd_spi_data.cs, 1); }
void set_cs_0() { gpio_set_level((gpio_num_t)epd_spi_data.cs, 0); }
void set_dc_1() { gpio_set_level((gpio_num_t)epd_spi_data.dc, 1); }
void set_dc_0() { gpio_set_level((gpio_num_t)epd_spi_data.dc, 0); }
void set_rst_1() { gpio_set_level((gpio_num_t)epd_spi_data.rst, 1); }
void set_rst_0() { gpio_set_level((gpio_num_t)epd_spi_data.rst, 0); }
void SPI_SendByte(uint8_t data);
void EPD_SendData(uint8_t data);
void EPD_SendCommand(uint8_t command);
void writeBytes(uint8_t* buffer, int len);
void writeBytes(const uint8_t* buffer, int len);
void EPD_SetWindows(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend);
void EPD_SetCursor(uint16_t Xstart, uint16_t Ystart);
void EPD_TurnOnDisplay();
void EPD_TurnOnDisplayPart();
};
#endif // __CUSTOM_LCD_DISPLAY_H__

View File

@@ -0,0 +1,178 @@
#include <driver/i2c_master.h>
#include <driver/spi_common.h>
#include <esp_lcd_panel_vendor.h>
#include <esp_log.h>
#include <stdio.h>
#include "application.h"
#include "button.h"
#include "codecs/es8311_audio_codec.h"
#include "config.h"
#include "custom_lcd_display.h"
#include "lvgl.h"
#include "mcp_server.h"
#include "wifi_board.h"
#include "axp2101.h"
#include "codecs/box_audio_codec.h"
#include "i2c_device.h"
#include "power_save_timer.h"
#define TAG "waveshare_epaper_3_97"
class Pmic : public Axp2101 {
public:
Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) {
WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable
WriteReg(0x27, 0x10); // hold 4s to power off
// Disable All DCs but DC1
WriteReg(0x80, 0x01);
// Disable All LDOs
WriteReg(0x90, 0x00);
WriteReg(0x91, 0x00);
// Set DC1 to 3.3V
WriteReg(0x82, (3300 - 1500) / 100);
// Set ALDO1 to 3.3V
WriteReg(0x92, (3300 - 500) / 100);
// Set ALDO2 to 3.3V
WriteReg(0x93, (3300 - 500) / 100);
// Set ALDO3 to 3.3V
WriteReg(0x94, (3300 - 500) / 100);
// Enable ALDO1、ALDO2、ALDO2
WriteReg(0x90, 0x07);
WriteReg(0x64, 0x03); // CV charger voltage setting to 4.2V
WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA
WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA,
// 0x09-300mA, 0x0A-400mA )
WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA
}
};
class WaveshareEsp32s3ePaper3inch97 : public WifiBoard {
private:
i2c_master_bus_handle_t i2c_bus_;
Pmic* pmic_ = nullptr;
Button boot_button_;
Button pwr_button_;
CustomEpdDisplay* display_;
PowerSaveTimer* power_save_timer_;
void InitializePowerSaveTimer() {
power_save_timer_ = new PowerSaveTimer(-1, 100, 300);
power_save_timer_->OnShutdownRequest([this]() {
GetDisplay()->SetChatMessage("system", "OFF");
vTaskDelay(pdMS_TO_TICKS(1000));
pmic_->PowerOff();
});
power_save_timer_->SetEnabled(true);
}
void InitializeI2c() {
i2c_master_bus_config_t i2c_bus_cfg = {};
i2c_bus_cfg.i2c_port = (i2c_port_t)0;
i2c_bus_cfg.sda_io_num = AUDIO_CODEC_I2C_SDA_PIN;
i2c_bus_cfg.scl_io_num = AUDIO_CODEC_I2C_SCL_PIN;
i2c_bus_cfg.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_bus_cfg.glitch_ignore_cnt = 7;
i2c_bus_cfg.intr_priority = 0;
i2c_bus_cfg.trans_queue_depth = 0;
i2c_bus_cfg.flags.enable_internal_pullup = 1;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_));
}
void InitializeButtons() {
boot_button_.OnClick([this]() {
auto& app = Application::GetInstance();
// During startup (before connected), pressing BOOT button enters Wi-Fi config mode
// without reboot
if (app.GetDeviceState() == kDeviceStateStarting) {
EnterWifiConfigMode();
return;
}
app.ToggleChatState();
});
pwr_button_.OnClick([this]() {
GetDisplay()->SetChatMessage("system", "OFF");
vTaskDelay(pdMS_TO_TICKS(1000));
pmic_->PowerOff();
});
}
void InitializeAxp2101() {
ESP_LOGI(TAG, "Init AXP2101");
pmic_ = new Pmic(i2c_bus_, 0x34);
}
void InitializeTools() {
auto& mcp_server = McpServer::GetInstance();
mcp_server.AddTool("self.disp.network", "重新配网", PropertyList(),
[this](const PropertyList&) -> ReturnValue {
EnterWifiConfigMode();
return true;
});
}
void InitializeEpdDisplay() {
custom_epd_spi_t epd_spi_data = {};
epd_spi_data.cs = EPD_CS_PIN;
epd_spi_data.dc = EPD_DC_PIN;
epd_spi_data.rst = EPD_RST_PIN;
epd_spi_data.busy = EPD_BUSY_PIN;
epd_spi_data.mosi = EPD_MOSI_PIN;
epd_spi_data.scl = EPD_SCK_PIN;
epd_spi_data.spi_host = EPD_SPI_NUM;
epd_spi_data.buffer_len = 48000;
display_ = new CustomEpdDisplay(NULL, NULL, EXAMPLE_LCD_WIDTH, EXAMPLE_LCD_HEIGHT,
DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X,
DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, epd_spi_data);
}
public:
WaveshareEsp32s3ePaper3inch97()
: boot_button_(BOOT_BUTTON_GPIO), pwr_button_(VBAT_PWR_GPIO, 1) {
InitializePowerSaveTimer();
InitializeI2c();
InitializeAxp2101();
InitializeButtons();
InitializeTools();
InitializeEpdDisplay();
}
virtual AudioCodec* GetAudioCodec() override {
static Es8311AudioCodec audio_codec(
i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE,
AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT,
AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR);
return &audio_codec;
}
virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override {
static bool last_discharging = false;
charging = pmic_->IsCharging();
discharging = pmic_->IsDischarging();
if (discharging != last_discharging) {
power_save_timer_->SetEnabled(discharging);
last_discharging = discharging;
}
level = pmic_->GetBatteryLevel();
return true;
}
virtual Display* GetDisplay() override { return display_; }
virtual void SetPowerSaveLevel(PowerSaveLevel level) override {
if (level != PowerSaveLevel::LOW_POWER) {
power_save_timer_->WakeUp();
}
WifiBoard::SetPowerSaveLevel(level);
}
};
DECLARE_BOARD(WaveshareEsp32s3ePaper3inch97);