mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Adds 1.54" e-ink display (gdew0154m09) support to waveshare_epaper component (#4939)
* Added GDEW0154M09 in waveshare_epaper component * noop change - trigger workflow * Make linter happy * Update test4.yaml * linter doing linty things * revert the newline removal. * revert to prove unstable test * add code back into test. * no partial updates supported yet - removed from test. * Update esphome/components/waveshare_epaper/waveshare_epaper.cpp Co-authored-by: Keith Burzinski <kbx81x@gmail.com> --------- Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
		| @@ -63,6 +63,7 @@ WaveshareEPaper7P5InHDB = waveshare_epaper_ns.class_( | |||||||
| WaveshareEPaper2P13InDKE = waveshare_epaper_ns.class_( | WaveshareEPaper2P13InDKE = waveshare_epaper_ns.class_( | ||||||
|     "WaveshareEPaper2P13InDKE", WaveshareEPaper |     "WaveshareEPaper2P13InDKE", WaveshareEPaper | ||||||
| ) | ) | ||||||
|  | GDEW0154M09 = waveshare_epaper_ns.class_("GDEW0154M09", WaveshareEPaper) | ||||||
|  |  | ||||||
| WaveshareEPaperTypeAModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeAModel") | WaveshareEPaperTypeAModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeAModel") | ||||||
| WaveshareEPaperTypeBModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeBModel") | WaveshareEPaperTypeBModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeBModel") | ||||||
| @@ -91,6 +92,7 @@ MODELS = { | |||||||
|     "7.50inv2alt": ("b", WaveshareEPaper7P5InV2alt), |     "7.50inv2alt": ("b", WaveshareEPaper7P5InV2alt), | ||||||
|     "7.50in-hd-b": ("b", WaveshareEPaper7P5InHDB), |     "7.50in-hd-b": ("b", WaveshareEPaper7P5InHDB), | ||||||
|     "2.13in-ttgo-dke": ("c", WaveshareEPaper2P13InDKE), |     "2.13in-ttgo-dke": ("c", WaveshareEPaper2P13InDKE), | ||||||
|  |     "1.54in-m5coreink-m09": ("c", GDEW0154M09), | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -763,6 +763,146 @@ void GDEY029T94::dump_config() { | |||||||
|   LOG_UPDATE_INTERVAL(this); |   LOG_UPDATE_INTERVAL(this); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ======================================================== | ||||||
|  | //     Good Display 1.54in black/white/grey GDEW0154M09 | ||||||
|  | // As used in M5Stack Core Ink | ||||||
|  | // Datasheet: | ||||||
|  | //  - https://v4.cecdn.yun300.cn/100001_1909185148/GDEW0154M09-200709.pdf | ||||||
|  | //  - https://github.com/m5stack/M5Core-Ink | ||||||
|  | // Reference code from GoodDisplay: | ||||||
|  | //  - https://github.com/GoodDisplay/E-paper-Display-Library-of-GoodDisplay/ | ||||||
|  | //  -> /Monochrome_E-paper-Display/1.54inch_JD79653_GDEW0154M09_200x200/ESP32-Arduino%20IDE/GDEW0154M09_Arduino.ino | ||||||
|  | // M5Stack Core Ink spec: | ||||||
|  | //  - https://docs.m5stack.com/en/core/coreink | ||||||
|  | // ======================================================== | ||||||
|  |  | ||||||
|  | void GDEW0154M09::initialize() { | ||||||
|  |   this->init_internal_(); | ||||||
|  |   ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE); | ||||||
|  |   this->lastbuff_ = allocator.allocate(this->get_buffer_length_()); | ||||||
|  |   if (this->lastbuff_ != nullptr) { | ||||||
|  |     memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_()); | ||||||
|  |   } | ||||||
|  |   this->clear_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GDEW0154M09::reset_() { | ||||||
|  |   // RST is inverse from other einks in this project | ||||||
|  |   if (this->reset_pin_ != nullptr) { | ||||||
|  |     this->reset_pin_->digital_write(false); | ||||||
|  |     delay(10); | ||||||
|  |     this->reset_pin_->digital_write(true); | ||||||
|  |     delay(10); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GDEW0154M09::init_internal_() { | ||||||
|  |   this->reset_(); | ||||||
|  |  | ||||||
|  |   // clang-format off | ||||||
|  |   // 200x200 resolution:        11 | ||||||
|  |   // LUT from OTP:              0 | ||||||
|  |   // B/W mode (doesn't work):   1 | ||||||
|  |   // scan-up:                   1 | ||||||
|  |   // shift-right:               1 | ||||||
|  |   // booster ON:                1 | ||||||
|  |   // no soft reset:             1 | ||||||
|  |   const uint8_t panel_setting_1 = 0b11011111; | ||||||
|  |  | ||||||
|  |   // VCOM status off            0 | ||||||
|  |   // Temp sensing default       1 | ||||||
|  |   // VGL Power Off Floating     1 | ||||||
|  |   // NORG expect refresh        1 | ||||||
|  |   // VCOM Off on displ off      0 | ||||||
|  |   const uint8_t panel_setting_2 = 0b01110; | ||||||
|  |  | ||||||
|  |   const uint8_t wf_t0154_cz_b3_list[] = { | ||||||
|  |       11, //  11 commands in list | ||||||
|  |       CMD_PSR_PANEL_SETTING, 2, panel_setting_1, panel_setting_2, | ||||||
|  |       CMD_UNDOCUMENTED_0x4D, 1, 0x55, | ||||||
|  |       CMD_UNDOCUMENTED_0xAA, 1, 0x0f, | ||||||
|  |       CMD_UNDOCUMENTED_0xE9, 1, 0x02, | ||||||
|  |       CMD_UNDOCUMENTED_0xB6, 1, 0x11, | ||||||
|  |       CMD_UNDOCUMENTED_0xF3, 1, 0x0a, | ||||||
|  |       CMD_TRES_RESOLUTION_SETTING, 3, 0xc8, 0x00, 0xc8, | ||||||
|  |       CMD_TCON_TCONSETTING, 1, 0x00, | ||||||
|  |       CMD_CDI_VCOM_DATA_INTERVAL, 1, 0xd7, | ||||||
|  |       CMD_PWS_POWER_SAVING, 1, 0x00, | ||||||
|  |       CMD_PON_POWER_ON, 0 | ||||||
|  |   }; | ||||||
|  |   // clang-format on | ||||||
|  |  | ||||||
|  |   this->write_init_list_(wf_t0154_cz_b3_list); | ||||||
|  |   delay(100);  // NOLINT | ||||||
|  |   this->wait_until_idle_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GDEW0154M09::write_init_list_(const uint8_t *list) { | ||||||
|  |   uint8_t list_limit = list[0]; | ||||||
|  |   uint8_t *start_ptr = ((uint8_t *) list + 1); | ||||||
|  |   for (uint8_t i = 0; i < list_limit; i++) { | ||||||
|  |     this->command(*(start_ptr + 0)); | ||||||
|  |     for (uint8_t dnum = 0; dnum < *(start_ptr + 1); dnum++) { | ||||||
|  |       this->data(*(start_ptr + 2 + dnum)); | ||||||
|  |     } | ||||||
|  |     start_ptr += (*(start_ptr + 1) + 2); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GDEW0154M09::clear_() { | ||||||
|  |   uint32_t pixsize = this->get_buffer_length_(); | ||||||
|  |   for (uint8_t j = 0; j < 2; j++) { | ||||||
|  |     this->command(CMD_DTM1_DATA_START_TRANS); | ||||||
|  |     for (int count = 0; count < pixsize; count++) { | ||||||
|  |       this->data(0x00); | ||||||
|  |     } | ||||||
|  |     this->command(CMD_DTM2_DATA_START_TRANS2); | ||||||
|  |     for (int count = 0; count < pixsize; count++) { | ||||||
|  |       this->data(0xff); | ||||||
|  |     } | ||||||
|  |     this->command(CMD_DISPLAY_REFRESH); | ||||||
|  |     delay(10); | ||||||
|  |     this->wait_until_idle_(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HOT GDEW0154M09::display() { | ||||||
|  |   this->init_internal_(); | ||||||
|  |   // "Mode 0 display" for now | ||||||
|  |   this->command(CMD_DTM1_DATA_START_TRANS); | ||||||
|  |   for (int i = 0; i < this->get_buffer_length_(); i++) { | ||||||
|  |     this->data(0xff); | ||||||
|  |   } | ||||||
|  |   this->command(CMD_DTM2_DATA_START_TRANS2);  // write 'new' data to SRAM | ||||||
|  |   for (int i = 0; i < this->get_buffer_length_(); i++) { | ||||||
|  |     this->data(this->buffer_[i]); | ||||||
|  |   } | ||||||
|  |   this->command(CMD_DISPLAY_REFRESH); | ||||||
|  |   delay(10); | ||||||
|  |   this->wait_until_idle_(); | ||||||
|  |   this->deep_sleep(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GDEW0154M09::deep_sleep() { | ||||||
|  |   // COMMAND DEEP SLEEP | ||||||
|  |   this->command(CMD_POF_POWER_OFF); | ||||||
|  |   this->wait_until_idle_(); | ||||||
|  |   delay(1000);  // NOLINT | ||||||
|  |   this->command(CMD_DSLP_DEEP_SLEEP); | ||||||
|  |   this->data(DATA_DSLP_DEEP_SLEEP); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int GDEW0154M09::get_width_internal() { return 200; } | ||||||
|  | int GDEW0154M09::get_height_internal() { return 200; } | ||||||
|  | void GDEW0154M09::dump_config() { | ||||||
|  |   LOG_DISPLAY("", "M5Stack CoreInk E-Paper (Good Display)", this); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Model: 1.54in Greyscale GDEW0154M09"); | ||||||
|  |   LOG_PIN("  Reset Pin: ", this->reset_pin_); | ||||||
|  |   LOG_PIN("  DC Pin: ", this->dc_pin_); | ||||||
|  |   LOG_PIN("  Busy Pin: ", this->busy_pin_); | ||||||
|  |   LOG_UPDATE_INTERVAL(this); | ||||||
|  | } | ||||||
|  |  | ||||||
| static const uint8_t LUT_VCOM_DC_4_2[] = { | static const uint8_t LUT_VCOM_DC_4_2[] = { | ||||||
|     0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01, |     0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01, | ||||||
|     0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |     0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|   | |||||||
| @@ -170,6 +170,46 @@ class GDEY029T94 : public WaveshareEPaper { | |||||||
|   int get_height_internal() override; |   int get_height_internal() override; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | class GDEW0154M09 : public WaveshareEPaper { | ||||||
|  |  public: | ||||||
|  |   void initialize() override; | ||||||
|  |   void display() override; | ||||||
|  |   void dump_config() override; | ||||||
|  |   void deep_sleep() override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   int get_width_internal() override; | ||||||
|  |   int get_height_internal() override; | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   static const uint8_t CMD_DTM1_DATA_START_TRANS = 0x10; | ||||||
|  |   static const uint8_t CMD_DTM2_DATA_START_TRANS2 = 0x13; | ||||||
|  |   static const uint8_t CMD_DISPLAY_REFRESH = 0x12; | ||||||
|  |   static const uint8_t CMD_AUTO_SEQ = 0x17; | ||||||
|  |   static const uint8_t DATA_AUTO_PON_DSR_POF_DSLP = 0xA7; | ||||||
|  |   static const uint8_t CMD_PSR_PANEL_SETTING = 0x00; | ||||||
|  |   static const uint8_t CMD_UNDOCUMENTED_0x4D = 0x4D;  //  NOLINT | ||||||
|  |   static const uint8_t CMD_UNDOCUMENTED_0xAA = 0xaa;  //  NOLINT | ||||||
|  |   static const uint8_t CMD_UNDOCUMENTED_0xE9 = 0xe9;  //  NOLINT | ||||||
|  |   static const uint8_t CMD_UNDOCUMENTED_0xB6 = 0xb6;  //  NOLINT | ||||||
|  |   static const uint8_t CMD_UNDOCUMENTED_0xF3 = 0xf3;  //  NOLINT | ||||||
|  |   static const uint8_t CMD_TRES_RESOLUTION_SETTING = 0x61; | ||||||
|  |   static const uint8_t CMD_TCON_TCONSETTING = 0x60; | ||||||
|  |   static const uint8_t CMD_CDI_VCOM_DATA_INTERVAL = 0x50; | ||||||
|  |   static const uint8_t CMD_POF_POWER_OFF = 0x02; | ||||||
|  |   static const uint8_t CMD_DSLP_DEEP_SLEEP = 0x07; | ||||||
|  |   static const uint8_t DATA_DSLP_DEEP_SLEEP = 0xA5; | ||||||
|  |   static const uint8_t CMD_PWS_POWER_SAVING = 0xe3; | ||||||
|  |   static const uint8_t CMD_PON_POWER_ON = 0x04; | ||||||
|  |   static const uint8_t CMD_PTL_PARTIAL_WINDOW = 0x90; | ||||||
|  |  | ||||||
|  |   uint8_t *lastbuff_ = nullptr; | ||||||
|  |   void reset_(); | ||||||
|  |   void clear_(); | ||||||
|  |   void write_init_list_(const uint8_t *list); | ||||||
|  |   void init_internal_(); | ||||||
|  | }; | ||||||
|  |  | ||||||
| class WaveshareEPaper2P9InB : public WaveshareEPaper { | class WaveshareEPaper2P9InB : public WaveshareEPaper { | ||||||
|  public: |  public: | ||||||
|   void initialize() override; |   void initialize() override; | ||||||
|   | |||||||
| @@ -504,6 +504,14 @@ display: | |||||||
|     full_update_every: 30 |     full_update_every: 30 | ||||||
|     lambda: |- |     lambda: |- | ||||||
|       it.rectangle(0, 0, it.get_width(), it.get_height()); |       it.rectangle(0, 0, it.get_width(), it.get_height()); | ||||||
|  |   - platform: waveshare_epaper | ||||||
|  |     cs_pin: GPIO23 | ||||||
|  |     dc_pin: GPIO23 | ||||||
|  |     busy_pin: GPIO23 | ||||||
|  |     reset_pin: GPIO23 | ||||||
|  |     model: 1.54in-m5coreink-m09 | ||||||
|  |     lambda: |- | ||||||
|  |       it.rectangle(0, 0, it.get_width(), it.get_height()); | ||||||
|   - platform: inkplate6 |   - platform: inkplate6 | ||||||
|     id: inkplate_display |     id: inkplate_display | ||||||
|     greyscale: false |     greyscale: false | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user