Mercurial > code > home > repos > front-door-display
view esp/update_lcd_block.h @ 21:a90cb6927c7d default tip
fix countdown queries. Display "now" instead of "In -0.4 hours"
author | drewp@bigasterisk.com |
---|---|
date | Sat, 07 Sep 2024 17:47:36 -0700 |
parents | 47795c3121f1 |
children |
line wrap: on
line source
#include <string> #include "esphome.h" // some from esphome; other code from // https://github.com/lvgl/lvgl_esp32_drivers/blob/master/lvgl_tft/ili9481.c // #include "esphome/components/ili9xxx/ili9xxx_display.h" static const char *const TAG = "ili9481direct"; namespace esphome { namespace ili9xxx { /* MIPI DCS Type1 */ #define ILI9481_CMD_NOP 0x00 #define ILI9481_CMD_SOFTWARE_RESET 0x01 #define ILI9481_CMD_READ_DISP_POWER_MODE 0x0A #define ILI9481_CMD_READ_DISP_MADCTRL 0x0B // bits 7:3 only #define ILI9481_CMD_READ_DISP_PIXEL_FORMAT 0x0C #define ILI9481_CMD_READ_DISP_IMAGE_MODE 0x0D #define ILI9481_CMD_READ_DISP_SIGNAL_MODE 0x0E #define ILI9481_CMD_READ_DISP_SELF_DIAGNOSTIC 0x0F // bits 7:6 only #define ILI9481_CMD_ENTER_SLEEP_MODE 0x10 #define ILI9481_CMD_SLEEP_OUT 0x11 #define ILI9481_CMD_PARTIAL_MODE_ON 0x12 #define ILI9481_CMD_NORMAL_DISP_MODE_ON 0x13 #define ILI9481_CMD_DISP_INVERSION_OFF 0x20 #define ILI9481_CMD_DISP_INVERSION_ON 0x21 #define ILI9481_CMD_DISPLAY_OFF 0x28 #define ILI9481_CMD_DISPLAY_ON 0x29 #define ILI9481_CMD_COLUMN_ADDRESS_SET 0x2A #define ILI9481_CMD_PAGE_ADDRESS_SET 0x2B #define ILI9481_CMD_MEMORY_WRITE 0x2C #define ILI9481_CMD_MEMORY_READ 0x2E #define ILI9481_CMD_PARTIAL_AREA 0x30 #define ILI9481_CMD_VERT_SCROLL_DEFINITION 0x33 #define ILI9481_CMD_TEARING_EFFECT_LINE_OFF 0x34 #define ILI9481_CMD_TEARING_EFFECT_LINE_ON 0x35 #define ILI9481_CMD_MEMORY_ACCESS_CONTROL 0x36 // bits 7:3,1:0 only #define ILI9481_CMD_VERT_SCROLL_START_ADDRESS 0x37 #define ILI9481_CMD_IDLE_MODE_OFF 0x38 #define ILI9481_CMD_IDLE_MODE_ON 0x39 #define ILI9481_CMD_COLMOD_PIXEL_FORMAT_SET 0x3A #define ILI9481_CMD_WRITE_MEMORY_CONTINUE 0x3C #define ILI9481_CMD_READ_MEMORY_CONTINUE 0x3E #define ILI9481_CMD_SET_TEAR_SCANLINE 0x44 #define ILI9481_CMD_GET_SCANLINE 0x45 #define ILI9481_DDB_START 0xA1 #define ILI9481_DDB_CONTINUE 0xA8 /* other */ #define ILI9481_CMD_ACCESS_PROTECT 0xB0 #define ILI9481_CMD_LOW_POWER_CONTROL 0xB1 #define ILI9481_CMD_FRAME_MEMORY_ACCESS 0xB3 #define ILI9481_CMD_DISPLAY_MODE 0xB4 #define ILI9481_CMD_DEVICE_CODE 0xBF #define ILI9481_CMD_PANEL_DRIVE 0xC0 #define ILI9481_CMD_DISP_TIMING_NORMAL 0xC1 #define ILI9481_CMD_DISP_TIMING_PARTIAL 0xC2 #define ILI9481_CMD_DISP_TIMING_IDLE 0xC3 #define ILI9481_CMD_FRAME_RATE 0xC5 #define ILI9481_CMD_INTERFACE_CONTROL 0xC6 #define ILI9481_CMD_GAMMA_SETTING 0xC8 #define ILI9481_CMD_POWER_SETTING 0xD0 #define ILI9481_CMD_VCOM_CONTROL 0xD1 #define ILI9481_CMD_POWER_CONTROL_NORMAL 0xD2 #define ILI9481_CMD_POWER_CONTROL_IDEL 0xD3 #define ILI9481_CMD_POWER_CONTROL_PARTIAL 0xD4 #define ILI9481_CMD_NVMEM_WRITE 0xE0 #define ILI9481_CMD_NVMEM_PROTECTION_KEY 0xE1 #define ILI9481_CMD_NVMEM_STATUS_READ 0xE2 #define ILI9481_CMD_NVMEM_PROTECTION 0xE3 typedef struct { uint8_t cmd; uint8_t data[16]; uint8_t databytes; // No of data in data; bit 7 = delay after set; 0xFF = end // of cmds. } lcd_init_cmd_t; lcd_init_cmd_t ili_init_cmds[] = { {ILI9481_CMD_SLEEP_OUT, {0x00}, 0x80}, // {ILI9481_CMD_POWER_SETTING, {0x07, 0x42, 0x18}, 3}, // from lvgl code {ILI9481_CMD_POWER_SETTING, {0x07, 0x41, 0x1D}, 3}, // from esphome code // {ILI9481_CMD_VCOM_CONTROL, {0x00, 0x07, 0x10}, 3}, // from lvgl code {ILI9481_CMD_VCOM_CONTROL, {0x00, 0x1c, 0x1f}, 3}, // from esphome code // {ILI9481_CMD_POWER_CONTROL_NORMAL, {0x01, 0x02}, 2}, // from lvgl code {ILI9481_CMD_POWER_CONTROL_NORMAL, {0x01, 0x11}, 2}, // from esphome code {ILI9481_CMD_PANEL_DRIVE, {0x10, 0x3B, 0x00, 0x02, 0x11}, 5}, {ILI9481_CMD_FRAME_RATE, {0x03}, 1}, {ILI9481_CMD_FRAME_MEMORY_ACCESS, {0x0, 0x0, 0x0, 0x0}, 4}, //{ILI9481_CMD_DISP_TIMING_NORMAL, {0x10, 0x10, 0x22}, 3}, {ILI9481_CMD_GAMMA_SETTING, {0x00, 0x32, 0x36, 0x45, 0x06, 0x16, 0x37, 0x75, 0x77, 0x54, 0x0C, 0x00}, 12}, #define ILI9481_ADDR_PAGE_ADDR_ORDER_B_TO_T 0x80 #define ILI9481_ADDR_COL_ADDR_ORDER_R_TO_L 0x40 #define ILI9481_ADDR_PAGE_COLUMN_ORDER_REVERSE 0x20 #define ILI9481_ADDR_LCD_REFRESH_BOT_TO_TOP 0x10 #define ILI9481_ADDR_BGR_ORDER 0x08 #define ILI9481_ADDR_HFLIP 0x02 #define ILI9481_ADDR_VFLIP 0x01 {ILI9481_CMD_MEMORY_ACCESS_CONTROL, {ILI9481_ADDR_BGR_ORDER | ILI9481_ADDR_HFLIP | 0}, 1}, {ILI9481_CMD_COLMOD_PIXEL_FORMAT_SET, {0x66}, 1}, // {ILI9481_CMD_COLMOD_PIXEL_FORMAT_SET, {0x55}, 1}, {ILI9481_CMD_DISP_INVERSION_ON, {}, 0x80}, {ILI9481_CMD_NORMAL_DISP_MODE_ON, {}, 0x80}, {ILI9481_CMD_DISPLAY_ON, {}, 0x80}, {0, {0}, 0xff}, }; class ILI9481Direct : public Component, public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING, // spi::DATA_RATE_40MHZ spi::DATA_RATE_10MHZ> { public: ILI9481Direct(esphome::spi::SPIComponent *spi) { spi_ = spi; } esphome::spi::SPIComponent *spi_; int width_ = 320; int height_ = 480; esp32::ESP32InternalGPIOPin *reset_pin_; esp32::ESP32InternalGPIOPin *dc_pin_; esp32::ESP32InternalGPIOPin *cs_pin_; void setup() override { this->setup_pins_(); this->init_lcd_(); } void loop() override {} void setup_pins_() { dc_pin_ = new esp32::ESP32InternalGPIOPin(); dc_pin_->set_pin(::GPIO_NUM_22); dc_pin_->set_inverted(false); dc_pin_->set_drive_strength(::GPIO_DRIVE_CAP_2); dc_pin_->set_flags(gpio::Flags::FLAG_OUTPUT); dc_pin_->setup(); // OUTPUT dc_pin_->digital_write(false); reset_pin_ = new esp32::ESP32InternalGPIOPin(); reset_pin_->set_pin(::GPIO_NUM_25); reset_pin_->set_inverted(false); reset_pin_->set_drive_strength(::GPIO_DRIVE_CAP_2); reset_pin_->set_flags(gpio::Flags::FLAG_OUTPUT); reset_pin_->setup(); // OUTPUT reset_pin_->digital_write(true); cs_pin_ = new esp32::ESP32InternalGPIOPin(); cs_pin_->set_pin(::GPIO_NUM_27); cs_pin_->set_inverted(false); cs_pin_->set_drive_strength(::GPIO_DRIVE_CAP_2); cs_pin_->set_flags(gpio::Flags::FLAG_OUTPUT); set_cs_pin(cs_pin_); set_spi_parent(spi_); spi_setup(); reset_(); } void init_lcd_() { command(ILI9481_CMD_SOFTWARE_RESET); delay(150); uint16_t cmd = 0; while (ili_init_cmds[cmd].databytes != 0xff) { command(ili_init_cmds[cmd].cmd); { start_data_(); write_array(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes & 0x1F); end_data_(); } if (ili_init_cmds[cmd].databytes & 0x80) { delay(150); } cmd++; } ESP_LOGI(TAG, "done init cmds"); } void blit(uint16_t xp, uint16_t yp, uint16_t w, uint16_t h, const unsigned char *&buf) { set_addr_window_(xp, yp, xp + w - 1, yp + h - 1); this->command(ILI9481_CMD_MEMORY_WRITE); { this->start_data_(); this->write_array(buf, static_cast<size_t>(h * w * 3)); this->end_data_(); } } void set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { command(ILI9481_CMD_COLUMN_ADDRESS_SET); { start_data_(); write_byte(x1 >> 8); write_byte(x1 & 0xFF); write_byte(x2 >> 8); write_byte(x2 & 0xFF); end_data_(); } command(ILI9481_CMD_PAGE_ADDRESS_SET); { start_data_(); write_byte(y1 >> 8); write_byte(y1 & 0xFF); write_byte(y2 >> 8); write_byte(y2 & 0xFF); end_data_(); } } void command(uint8_t value) { this->start_command_(); this->write_byte(value); this->end_command_(); } void start_command_() { this->dc_pin_->digital_write(false); this->enable(); } void end_command_() { this->disable(); } void start_data_() { this->dc_pin_->digital_write(true); this->enable(); } void end_data_() { this->disable(); } void reset_() { if (this->reset_pin_ != nullptr) { this->reset_pin_->digital_write(false); delay(20); this->reset_pin_->digital_write(true); delay(20); } } }; void update_lcd_block(ILI9481Direct *lcd, std::string &x) { #if 0 std::string localPayload = x; const unsigned char *buf = reinterpret_cast<const unsigned char*>(localPayload.data()); #else const unsigned char *buf = reinterpret_cast<const unsigned char *>(x.data()); #endif uint16_t seq, xp, yp, w, h; #define readu16() \ (static_cast<const uint16_t>(*(buf++)) | \ (static_cast<const uint16_t>(*(buf++)) << 8)) seq = readu16(); xp = readu16(); yp = readu16(); w = readu16(); h = readu16(); char seqDia[] = " "; seqDia[seq % 10] = '%'; ESP_LOGD("dbg", "seq=%hu%s xp=%hu, yp=%hu, w=%hu, h=%hu, full payload=%d bytes", seq, seqDia, xp, yp, w, h, x.size()); lcd->blit(xp, yp, w, h, buf); } } // namespace ili9xxx } // namespace esphome