mirror of
https://github.com/78/xiaozhi-esp32.git
synced 2026-01-14 01:07:30 +08:00
Add support for Waveshare ESP32-S3-ePaper-1.54 board (#1375)
* Add support for Waveshare ESP32-S3-ePaper-1.54 board * 根据审核,做对应的修改 * fix:优化格式,主要是对头文件引用进行修改 --------- Co-authored-by: Tomato Me <55608753+wurongmin@users.noreply.github.com>
This commit is contained in:
parent
ba10b2a2d2
commit
7f332f120c
@ -264,6 +264,10 @@ elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5B)
|
||||
set(BUILTIN_TEXT_FONT font_puhui_basic_16_4)
|
||||
set(BUILTIN_ICON_FONT font_awesome_16_4)
|
||||
set(DEFAULT_EMOJI_COLLECTION twemoji_32)
|
||||
elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_ePaper_1_54)
|
||||
set(BOARD_TYPE "waveshare-s3-epaper-1.54")
|
||||
set(BUILTIN_TEXT_FONT font_puhui_basic_20_4)
|
||||
set(BUILTIN_ICON_FONT font_awesome_20_4)
|
||||
elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_49)
|
||||
set(BOARD_TYPE "waveshare-s3-touch-lcd-3.49")
|
||||
set(LVGL_TEXT_FONT font_puhui_basic_30_4)
|
||||
|
||||
@ -282,6 +282,9 @@ choice BOARD_TYPE
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.5"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_ePaper_1_54
|
||||
bool "Waveshare ESP32-S3-ePaper-1.54"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5B
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.5B"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
|
||||
48
main/boards/waveshare-s3-epaper-1.54/README.md
Normal file
48
main/boards/waveshare-s3-epaper-1.54/README.md
Normal file
@ -0,0 +1,48 @@
|
||||
# 产品链接
|
||||
|
||||
[微雪电子 ESP32-S3-ePaper-1.54](https://www.waveshare.net/shop/ESP32-S3-ePaper-1.54.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-1.54
|
||||
```
|
||||
|
||||
**编译**
|
||||
|
||||
```ba
|
||||
idf.py build
|
||||
```
|
||||
|
||||
**下载并打开串口终端**
|
||||
|
||||
```bash
|
||||
idf.py build flash monitor
|
||||
```
|
||||
|
||||
58
main/boards/waveshare-s3-epaper-1.54/board_power_bsp.cc
Normal file
58
main/boards/waveshare-s3-epaper-1.54/board_power_bsp.cc
Normal file
@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include "board_power_bsp.h"
|
||||
|
||||
void BoardPowerBsp::PowerLedTask(void *arg) {
|
||||
gpio_config_t gpio_conf = {};
|
||||
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_conf.mode = GPIO_MODE_OUTPUT;
|
||||
gpio_conf.pin_bit_mask = (0x1ULL << GPIO_NUM_3);
|
||||
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));
|
||||
for (;;) {
|
||||
gpio_set_level(GPIO_NUM_3, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
gpio_set_level(GPIO_NUM_3, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
}
|
||||
|
||||
BoardPowerBsp::BoardPowerBsp(int epdPowerPin, int audioPowerPin, int vbatPowerPin) : epdPowerPin_(epdPowerPin), audioPowerPin_(audioPowerPin), vbatPowerPin_(vbatPowerPin) {
|
||||
gpio_config_t gpio_conf = {};
|
||||
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_conf.mode = GPIO_MODE_OUTPUT;
|
||||
gpio_conf.pin_bit_mask = (0x1ULL << epdPowerPin_) | (0x1ULL << audioPowerPin_) | (0x1ULL << vbatPowerPin_);
|
||||
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));
|
||||
xTaskCreatePinnedToCore(PowerLedTask, "PowerLedTask", 3 * 1024, NULL, 2, NULL, 0);
|
||||
}
|
||||
|
||||
BoardPowerBsp::~BoardPowerBsp() {
|
||||
}
|
||||
|
||||
void BoardPowerBsp::PowerEpdOn() {
|
||||
gpio_set_level((gpio_num_t) epdPowerPin_, 0);
|
||||
}
|
||||
|
||||
void BoardPowerBsp::PowerEpdOff() {
|
||||
gpio_set_level((gpio_num_t) epdPowerPin_, 1);
|
||||
}
|
||||
|
||||
void BoardPowerBsp::PowerAudioOn() {
|
||||
gpio_set_level((gpio_num_t) audioPowerPin_, 0);
|
||||
}
|
||||
|
||||
void BoardPowerBsp::PowerAudioOff() {
|
||||
gpio_set_level((gpio_num_t) audioPowerPin_, 1);
|
||||
}
|
||||
|
||||
void BoardPowerBsp::VbatPowerOn() {
|
||||
gpio_set_level((gpio_num_t) vbatPowerPin_, 1);
|
||||
}
|
||||
|
||||
void BoardPowerBsp::VbatPowerOff() {
|
||||
gpio_set_level((gpio_num_t) vbatPowerPin_, 0);
|
||||
}
|
||||
23
main/boards/waveshare-s3-epaper-1.54/board_power_bsp.h
Normal file
23
main/boards/waveshare-s3-epaper-1.54/board_power_bsp.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __BOARD_POWER_BSP_H__
|
||||
#define __BOARD_POWER_BSP_H__
|
||||
|
||||
class BoardPowerBsp {
|
||||
private:
|
||||
const int epdPowerPin_;
|
||||
const int audioPowerPin_;
|
||||
const int vbatPowerPin_;
|
||||
|
||||
static void PowerLedTask(void *arg);
|
||||
|
||||
public:
|
||||
BoardPowerBsp(int epdPowerPin, int audioPowerPin, int vbatPowerPin);
|
||||
~BoardPowerBsp();
|
||||
void PowerEpdOn();
|
||||
void PowerEpdOff();
|
||||
void PowerAudioOn();
|
||||
void PowerAudioOff();
|
||||
void VbatPowerOn();
|
||||
void VbatPowerOff();
|
||||
};
|
||||
|
||||
#endif
|
||||
50
main/boards/waveshare-s3-epaper-1.54/config.h
Normal file
50
main/boards/waveshare-s3-epaper-1.54/config.h
Normal file
@ -0,0 +1,50 @@
|
||||
#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_14
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_38
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_16
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_45
|
||||
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_46
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48
|
||||
#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR
|
||||
|
||||
#define BOOT_BUTTON_GPIO GPIO_NUM_0
|
||||
#define VBAT_PWR_GPIO GPIO_NUM_18
|
||||
|
||||
/*EPD port Init*/
|
||||
#define EPD_SPI_NUM SPI3_HOST
|
||||
|
||||
#define EPD_DC_PIN GPIO_NUM_10
|
||||
#define EPD_CS_PIN GPIO_NUM_11
|
||||
#define EPD_SCK_PIN GPIO_NUM_12
|
||||
#define EPD_MOSI_PIN GPIO_NUM_13
|
||||
#define EPD_RST_PIN GPIO_NUM_9
|
||||
#define EPD_BUSY_PIN GPIO_NUM_8
|
||||
|
||||
#define EXAMPLE_LCD_WIDTH 200
|
||||
#define EXAMPLE_LCD_HEIGHT 200
|
||||
|
||||
/*DEV POWER init*/
|
||||
#define EPD_PWR_PIN GPIO_NUM_6
|
||||
#define Audio_PWR_PIN GPIO_NUM_42
|
||||
#define VBAT_PWR_PIN GPIO_NUM_17
|
||||
|
||||
#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_
|
||||
12
main/boards/waveshare-s3-epaper-1.54/config.json
Normal file
12
main/boards/waveshare-s3-epaper-1.54/config.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"target": "esp32s3",
|
||||
"builds": [
|
||||
{
|
||||
"name": "waveshare-s3-epaper-1.54",
|
||||
"sdkconfig_append": [
|
||||
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=partitions/v2/8m.csv",
|
||||
"CONFIG_ESPTOOLPY_FLASHSIZE=8MB"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
404
main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.cc
Normal file
404
main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.cc
Normal file
@ -0,0 +1,404 @@
|
||||
#include <stdio.h>
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <vector>
|
||||
#include <esp_log.h>
|
||||
#include "custom_lcd_display.h"
|
||||
#include "board.h"
|
||||
#include "config.h"
|
||||
#include "esp_lvgl_port.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define TAG "CustomLcdDisplay"
|
||||
|
||||
#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)
|
||||
|
||||
const uint8_t WF_Full_1IN54[159] =
|
||||
{
|
||||
0x80,0x48,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x40,0x48,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x80,0x48,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x40,0x48,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0xA,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x8,0x1,0x0,0x8,0x1,0x0,0x2,
|
||||
0xA,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
|
||||
0x22,0x17,0x41,0x0,0x32,0x20
|
||||
};
|
||||
|
||||
const uint8_t WF_PARTIAL_1IN54_0[159] =
|
||||
{
|
||||
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0xF,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x1,0x1,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
|
||||
0x02,0x17,0x41,0xB0,0x32,0x28,
|
||||
};
|
||||
|
||||
void CustomLcdDisplay::lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p) {
|
||||
assert(disp != NULL);
|
||||
CustomLcdDisplay *driver = (CustomLcdDisplay *) 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);
|
||||
}
|
||||
|
||||
CustomLcdDisplay::CustomLcdDisplay(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_lcd_spi_t _lcd_spi_data) :
|
||||
LcdDisplay(panel_io, panel, width, height),
|
||||
lcd_spi_data(_lcd_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(lcd_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();
|
||||
EPD_Clear();
|
||||
EPD_Display();
|
||||
EPD_DisplayPartBaseImage();
|
||||
EPD_Init_Partial(); // 局部刷新初始化
|
||||
|
||||
lvgl_port_unlock();
|
||||
if (display_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to add display");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "ui start");
|
||||
|
||||
SetupUI();
|
||||
}
|
||||
|
||||
CustomLcdDisplay::~CustomLcdDisplay() {
|
||||
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::spi_gpio_init() {
|
||||
int rst = lcd_spi_data.rst;
|
||||
int cs = lcd_spi_data.cs;
|
||||
int dc = lcd_spi_data.dc;
|
||||
int busy = lcd_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 CustomLcdDisplay::spi_port_init() {
|
||||
int mosi = lcd_spi_data.mosi;
|
||||
int scl = lcd_spi_data.scl;
|
||||
int spi_host = lcd_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 = Width * Height;
|
||||
|
||||
spi_device_interface_config_t devcfg = {};
|
||||
devcfg.spics_io_num = -1;
|
||||
devcfg.clock_speed_hz = 40 * 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 CustomLcdDisplay::read_busy() {
|
||||
int busy = lcd_spi_data.busy;
|
||||
while (gpio_get_level((gpio_num_t) busy) == 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(5)); // LOW: idle, HIGH: busy
|
||||
}
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::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 CustomLcdDisplay::EPD_SendData(uint8_t data) {
|
||||
set_dc_1();
|
||||
set_cs_0();
|
||||
SPI_SendByte(data);
|
||||
set_cs_1();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_SendCommand(uint8_t command) {
|
||||
set_dc_0();
|
||||
set_cs_0();
|
||||
SPI_SendByte(command);
|
||||
set_cs_1();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::writeBytes(uint8_t *buffer, int len) {
|
||||
set_dc_1();
|
||||
set_cs_0();
|
||||
esp_err_t ret;
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.length = 8 * len;
|
||||
t.tx_buffer = buffer;
|
||||
ret = spi_device_polling_transmit(spi, &t); // Transmit!
|
||||
assert(ret == ESP_OK);
|
||||
set_cs_1();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::writeBytes(const uint8_t *buffer, int len) {
|
||||
set_dc_1();
|
||||
set_cs_0();
|
||||
esp_err_t ret;
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.length = 8 * len;
|
||||
t.tx_buffer = buffer;
|
||||
ret = spi_device_polling_transmit(spi, &t); // Transmit!
|
||||
assert(ret == ESP_OK);
|
||||
set_cs_1();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::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 >> 3) & 0xFF);
|
||||
EPD_SendData((Xend >> 3) & 0xFF);
|
||||
|
||||
EPD_SendCommand(0x45); // SET_RAM_Y_ADDRESS_START_END_POSITION
|
||||
EPD_SendData(Ystart & 0xFF);
|
||||
EPD_SendData((Ystart >> 8) & 0xFF);
|
||||
EPD_SendData(Yend & 0xFF);
|
||||
EPD_SendData((Yend >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_SetCursor(uint16_t Xstart, uint16_t Ystart) {
|
||||
EPD_SendCommand(0x4E); // SET_RAM_X_ADDRESS_COUNTER
|
||||
EPD_SendData(Xstart & 0xFF);
|
||||
|
||||
EPD_SendCommand(0x4F); // SET_RAM_Y_ADDRESS_COUNTER
|
||||
EPD_SendData(Ystart & 0xFF);
|
||||
EPD_SendData((Ystart >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_SetLut(const uint8_t *lut) {
|
||||
EPD_SendCommand(0x32);
|
||||
writeBytes(lut, 153);
|
||||
read_busy();
|
||||
|
||||
EPD_SendCommand(0x3f);
|
||||
EPD_SendData(lut[153]);
|
||||
|
||||
EPD_SendCommand(0x03);
|
||||
EPD_SendData(lut[154]);
|
||||
|
||||
EPD_SendCommand(0x04);
|
||||
EPD_SendData(lut[155]);
|
||||
EPD_SendData(lut[156]);
|
||||
EPD_SendData(lut[157]);
|
||||
|
||||
EPD_SendCommand(0x2c);
|
||||
EPD_SendData(lut[158]);
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_TurnOnDisplay() {
|
||||
EPD_SendCommand(0x22);
|
||||
EPD_SendData(0xc7);
|
||||
EPD_SendCommand(0x20);
|
||||
read_busy();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_TurnOnDisplayPart() {
|
||||
EPD_SendCommand(0x22);
|
||||
EPD_SendData(0xcf);
|
||||
EPD_SendCommand(0x20);
|
||||
read_busy();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_Init() {
|
||||
set_rst_1();
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
set_rst_0();
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
set_rst_1();
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
|
||||
read_busy();
|
||||
EPD_SendCommand(0x12); // SWRESET
|
||||
read_busy();
|
||||
|
||||
EPD_SendCommand(0x01); // Driver output control
|
||||
EPD_SendData(0xC7);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x01);
|
||||
|
||||
EPD_SendCommand(0x11); // data entry mode
|
||||
EPD_SendData(0x01);
|
||||
|
||||
EPD_SetWindows(0, Width - 1, Height - 1, 0);
|
||||
|
||||
EPD_SendCommand(0x3C); // BorderWavefrom
|
||||
EPD_SendData(0x01);
|
||||
|
||||
EPD_SendCommand(0x18);
|
||||
EPD_SendData(0x80);
|
||||
|
||||
EPD_SendCommand(0x22); // Load Temperature and waveform setting.
|
||||
EPD_SendData(0XB1);
|
||||
EPD_SendCommand(0x20);
|
||||
|
||||
EPD_SetCursor(0, Height - 1);
|
||||
read_busy();
|
||||
|
||||
EPD_SetLut(WF_Full_1IN54);
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_Clear() {
|
||||
int buffer_len = lcd_spi_data.buffer_len;
|
||||
memset(buffer, 0xff, buffer_len);
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_Display() {
|
||||
int buffer_len = lcd_spi_data.buffer_len;
|
||||
EPD_SendCommand(0x24);
|
||||
assert(buffer);
|
||||
writeBytes(buffer, buffer_len);
|
||||
EPD_TurnOnDisplay();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_DisplayPartBaseImage() {
|
||||
int buffer_len = lcd_spi_data.buffer_len;
|
||||
EPD_SendCommand(0x24);
|
||||
assert(buffer);
|
||||
writeBytes(buffer, buffer_len);
|
||||
EPD_SendCommand(0x26);
|
||||
writeBytes(buffer, buffer_len);
|
||||
EPD_TurnOnDisplay();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_Init_Partial() {
|
||||
set_rst_1();
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
set_rst_0();
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
set_rst_1();
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
|
||||
read_busy();
|
||||
|
||||
EPD_SetLut(WF_PARTIAL_1IN54_0);
|
||||
|
||||
EPD_SendCommand(0x37);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x40);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x00);
|
||||
EPD_SendData(0x00);
|
||||
|
||||
EPD_SendCommand(0x3C); // BorderWavefrom
|
||||
EPD_SendData(0x80);
|
||||
|
||||
EPD_SendCommand(0x22);
|
||||
EPD_SendData(0xc0);
|
||||
EPD_SendCommand(0x20);
|
||||
read_busy();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::EPD_DisplayPart() {
|
||||
EPD_SendCommand(0x24);
|
||||
assert(buffer);
|
||||
writeBytes(buffer, 5000);
|
||||
EPD_TurnOnDisplayPart();
|
||||
}
|
||||
|
||||
void CustomLcdDisplay::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 * 25 + (x >> 3);
|
||||
uint8_t bit = 7 - (x & 0x07);
|
||||
if (color == DRIVER_COLOR_WHITE) {
|
||||
buffer[index] |= (0x01 << bit);
|
||||
} else {
|
||||
buffer[index] &= ~(0x01 << bit);
|
||||
}
|
||||
}
|
||||
75
main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.h
Normal file
75
main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.h
Normal file
@ -0,0 +1,75 @@
|
||||
#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_lcd_spi_t;
|
||||
|
||||
|
||||
class CustomLcdDisplay : public LcdDisplay {
|
||||
public:
|
||||
CustomLcdDisplay(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_lcd_spi_t _lcd_spi_data);
|
||||
~CustomLcdDisplay();
|
||||
|
||||
void EPD_Init(); /* 墨水屏初始化 */
|
||||
void EPD_Clear(); /* 清空屏幕 */
|
||||
void EPD_Display(); /* 刷buffer到墨水屏 */
|
||||
|
||||
/*快速刷新*/
|
||||
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_lcd_spi_t lcd_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)lcd_spi_data.cs,1);}
|
||||
void set_cs_0(){gpio_set_level((gpio_num_t)lcd_spi_data.cs,0);}
|
||||
void set_dc_1(){gpio_set_level((gpio_num_t)lcd_spi_data.dc,1);}
|
||||
void set_dc_0(){gpio_set_level((gpio_num_t)lcd_spi_data.dc,0);}
|
||||
void set_rst_1(){gpio_set_level((gpio_num_t)lcd_spi_data.rst,1);}
|
||||
void set_rst_0(){gpio_set_level((gpio_num_t)lcd_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_SetLut(const uint8_t *lut);
|
||||
void EPD_TurnOnDisplay();
|
||||
void EPD_TurnOnDisplayPart();
|
||||
};
|
||||
|
||||
#endif // __CUSTOM_LCD_DISPLAY_H__
|
||||
110
main/boards/waveshare-s3-epaper-1.54/waveshare-s3-epaper-1.54.cc
Normal file
110
main/boards/waveshare-s3-epaper-1.54/waveshare-s3-epaper-1.54.cc
Normal file
@ -0,0 +1,110 @@
|
||||
#include <stdio.h>
|
||||
#include <driver/i2c_master.h>
|
||||
#include <driver/spi_common.h>
|
||||
#include <esp_lcd_panel_vendor.h>
|
||||
#include <esp_log.h>
|
||||
#include "wifi_station.h"
|
||||
#include "application.h"
|
||||
#include "button.h"
|
||||
#include "codecs/es8311_audio_codec.h"
|
||||
#include "config.h"
|
||||
#include "wifi_board.h"
|
||||
#include "board_power_bsp.h"
|
||||
#include "custom_lcd_display.h"
|
||||
#include "lvgl.h"
|
||||
#include "mcp_server.h"
|
||||
|
||||
#define TAG "waveshare_epaper_1_54"
|
||||
|
||||
class CustomBoard : public WifiBoard {
|
||||
private:
|
||||
i2c_master_bus_handle_t i2c_bus_;
|
||||
Button boot_button_;
|
||||
Button pwr_button_;
|
||||
CustomLcdDisplay *display_;
|
||||
BoardPowerBsp *power_;
|
||||
adc_oneshot_unit_handle_t adc1_handle;
|
||||
adc_cali_handle_t cali_handle;
|
||||
|
||||
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();
|
||||
if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) {
|
||||
ResetWifiConfiguration();
|
||||
}
|
||||
app.ToggleChatState();
|
||||
});
|
||||
|
||||
pwr_button_.OnLongPress([this]() {
|
||||
GetDisplay()->SetChatMessage("system", "OFF");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
power_->PowerAudioOff();
|
||||
power_->PowerEpdOff();
|
||||
power_->VbatPowerOff();
|
||||
});
|
||||
}
|
||||
|
||||
void InitializeTools() {
|
||||
auto &mcp_server = McpServer::GetInstance();
|
||||
mcp_server.AddTool("self.disp.network", "重新配网", PropertyList(), [this](const PropertyList &) -> ReturnValue {
|
||||
ResetWifiConfiguration();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void InitializeLcdDisplay() {
|
||||
custom_lcd_spi_t lcd_spi_data = {};
|
||||
lcd_spi_data.cs = EPD_CS_PIN;
|
||||
lcd_spi_data.dc = EPD_DC_PIN;
|
||||
lcd_spi_data.rst = EPD_RST_PIN;
|
||||
lcd_spi_data.busy = EPD_BUSY_PIN;
|
||||
lcd_spi_data.mosi = EPD_MOSI_PIN;
|
||||
lcd_spi_data.scl = EPD_SCK_PIN;
|
||||
lcd_spi_data.spi_host = EPD_SPI_NUM;
|
||||
lcd_spi_data.buffer_len = 5000;
|
||||
display_ = new CustomLcdDisplay(NULL, NULL, EXAMPLE_LCD_WIDTH, EXAMPLE_LCD_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, lcd_spi_data);
|
||||
}
|
||||
|
||||
void Power_Init() {
|
||||
power_ = new BoardPowerBsp(EPD_PWR_PIN, Audio_PWR_PIN, VBAT_PWR_PIN);
|
||||
power_->VbatPowerOn();
|
||||
power_->PowerAudioOn();
|
||||
power_->PowerEpdOn();
|
||||
do {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
} while (!gpio_get_level(VBAT_PWR_GPIO));
|
||||
}
|
||||
|
||||
public:
|
||||
CustomBoard() : boot_button_(BOOT_BUTTON_GPIO), pwr_button_(VBAT_PWR_GPIO) {
|
||||
Power_Init();
|
||||
InitializeI2c();
|
||||
InitializeButtons();
|
||||
InitializeTools();
|
||||
InitializeLcdDisplay();
|
||||
}
|
||||
|
||||
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 Display *GetDisplay() override {
|
||||
return display_;
|
||||
}
|
||||
};
|
||||
|
||||
DECLARE_BOARD(CustomBoard);
|
||||
Loading…
Reference in New Issue
Block a user