mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add SSD1325 Display Component (#736)
* add ssd1325 component * fix i2c * remove ssd1325 i2c * add test * set max contrast * No macros - see styleguide * Remove invalid function * Formatting Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
		
				
					committed by
					
						 Otto Winter
						Otto Winter
					
				
			
			
				
	
			
			
			
						parent
						
							e553c0768e
						
					
				
				
					commit
					58b6311821
				
			
							
								
								
									
										42
									
								
								esphome/components/ssd1325_base/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								esphome/components/ssd1325_base/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import display | ||||
| from esphome.const import CONF_EXTERNAL_VCC, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN | ||||
| from esphome.core import coroutine | ||||
|  | ||||
| ssd1325_base_ns = cg.esphome_ns.namespace('ssd1325_base') | ||||
| SSD1325 = ssd1325_base_ns.class_('SSD1325', cg.PollingComponent, display.DisplayBuffer) | ||||
| SSD1325Model = ssd1325_base_ns.enum('SSD1325Model') | ||||
|  | ||||
| MODELS = { | ||||
|     'SSD1325_128X32': SSD1325Model.SSD1325_MODEL_128_32, | ||||
|     'SSD1325_128X64': SSD1325Model.SSD1325_MODEL_128_64, | ||||
|     'SSD1325_96X16': SSD1325Model.SSD1325_MODEL_96_16, | ||||
|     'SSD1325_64X48': SSD1325Model.SSD1325_MODEL_64_48, | ||||
| } | ||||
|  | ||||
| SSD1325_MODEL = cv.enum(MODELS, upper=True, space="_") | ||||
|  | ||||
| SSD1325_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ | ||||
|     cv.Required(CONF_MODEL): SSD1325_MODEL, | ||||
|     cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Optional(CONF_EXTERNAL_VCC): cv.boolean, | ||||
| }).extend(cv.polling_component_schema('1s')) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def setup_ssd1036(var, config): | ||||
|     yield cg.register_component(var, config) | ||||
|     yield display.register_display(var, config) | ||||
|  | ||||
|     cg.add(var.set_model(config[CONF_MODEL])) | ||||
|     if CONF_RESET_PIN in config: | ||||
|         reset = yield cg.gpio_pin_expression(config[CONF_RESET_PIN]) | ||||
|         cg.add(var.set_reset_pin(reset)) | ||||
|     if CONF_EXTERNAL_VCC in config: | ||||
|         cg.add(var.set_external_vcc(config[CONF_EXTERNAL_VCC])) | ||||
|     if CONF_LAMBDA in config: | ||||
|         lambda_ = yield cg.process_lambda( | ||||
|             config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) | ||||
|         cg.add(var.set_writer(lambda_)) | ||||
							
								
								
									
										177
									
								
								esphome/components/ssd1325_base/ssd1325_base.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								esphome/components/ssd1325_base/ssd1325_base.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| #include "ssd1325_base.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/helpers.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace ssd1325_base { | ||||
|  | ||||
| static const char *TAG = "ssd1325"; | ||||
|  | ||||
| static const uint8_t BLACK = 0; | ||||
| static const uint8_t WHITE = 1; | ||||
|  | ||||
| static const uint8_t SSD1325_SETCOLADDR = 0x15; | ||||
| static const uint8_t SSD1325_SETROWADDR = 0x75; | ||||
| static const uint8_t SSD1325_SETCONTRAST = 0x81; | ||||
| static const uint8_t SSD1325_SETCURRENT = 0x84; | ||||
|  | ||||
| static const uint8_t SSD1325_SETREMAP = 0xA0; | ||||
| static const uint8_t SSD1325_SETSTARTLINE = 0xA1; | ||||
| static const uint8_t SSD1325_SETOFFSET = 0xA2; | ||||
| static const uint8_t SSD1325_NORMALDISPLAY = 0xA4; | ||||
| static const uint8_t SSD1325_DISPLAYALLON = 0xA5; | ||||
| static const uint8_t SSD1325_DISPLAYALLOFF = 0xA6; | ||||
| static const uint8_t SSD1325_INVERTDISPLAY = 0xA7; | ||||
| static const uint8_t SSD1325_SETMULTIPLEX = 0xA8; | ||||
| static const uint8_t SSD1325_MASTERCONFIG = 0xAD; | ||||
| static const uint8_t SSD1325_DISPLAYOFF = 0xAE; | ||||
| static const uint8_t SSD1325_DISPLAYON = 0xAF; | ||||
|  | ||||
| static const uint8_t SSD1325_SETPRECHARGECOMPENABLE = 0xB0; | ||||
| static const uint8_t SSD1325_SETPHASELEN = 0xB1; | ||||
| static const uint8_t SSD1325_SETROWPERIOD = 0xB2; | ||||
| static const uint8_t SSD1325_SETCLOCK = 0xB3; | ||||
| static const uint8_t SSD1325_SETPRECHARGECOMP = 0xB4; | ||||
| static const uint8_t SSD1325_SETGRAYTABLE = 0xB8; | ||||
| static const uint8_t SSD1325_SETPRECHARGEVOLTAGE = 0xBC; | ||||
| static const uint8_t SSD1325_SETVCOMLEVEL = 0xBE; | ||||
| static const uint8_t SSD1325_SETVSL = 0xBF; | ||||
|  | ||||
| static const uint8_t SSD1325_GFXACCEL = 0x23; | ||||
| static const uint8_t SSD1325_DRAWRECT = 0x24; | ||||
| static const uint8_t SSD1325_COPY = 0x25; | ||||
|  | ||||
| void SSD1325::setup() { | ||||
|   this->init_internal_(this->get_buffer_length_()); | ||||
|  | ||||
|   this->command(SSD1325_DISPLAYOFF);   /* display off */ | ||||
|   this->command(SSD1325_SETCLOCK);     /* set osc division */ | ||||
|   this->command(0xF1);                 /* 145 */ | ||||
|   this->command(SSD1325_SETMULTIPLEX); /* multiplex ratio */ | ||||
|   this->command(0x3f);                 /* duty = 1/64 */ | ||||
|   this->command(SSD1325_SETOFFSET);    /* set display offset --- */ | ||||
|   this->command(0x4C);                 /* 76 */ | ||||
|   this->command(SSD1325_SETSTARTLINE); /*set start line */ | ||||
|   this->command(0x00);                 /* ------ */ | ||||
|   this->command(SSD1325_MASTERCONFIG); /*Set Master Config DC/DC Converter*/ | ||||
|   this->command(0x02); | ||||
|   this->command(SSD1325_SETREMAP); /* set segment remap------ */ | ||||
|   this->command(0x56); | ||||
|   this->command(SSD1325_SETCURRENT + 0x2); /* Set Full Current Range */ | ||||
|   this->command(SSD1325_SETGRAYTABLE); | ||||
|   this->command(0x01); | ||||
|   this->command(0x11); | ||||
|   this->command(0x22); | ||||
|   this->command(0x32); | ||||
|   this->command(0x43); | ||||
|   this->command(0x54); | ||||
|   this->command(0x65); | ||||
|   this->command(0x76); | ||||
|   this->command(SSD1325_SETCONTRAST); /* set contrast current */ | ||||
|   this->command(0x7F);                // max! | ||||
|   this->command(SSD1325_SETROWPERIOD); | ||||
|   this->command(0x51); | ||||
|   this->command(SSD1325_SETPHASELEN); | ||||
|   this->command(0x55); | ||||
|   this->command(SSD1325_SETPRECHARGECOMP); | ||||
|   this->command(0x02); | ||||
|   this->command(SSD1325_SETPRECHARGECOMPENABLE); | ||||
|   this->command(0x28); | ||||
|   this->command(SSD1325_SETVCOMLEVEL);  // Set High Voltage Level of COM Pin | ||||
|   this->command(0x1C);                  //? | ||||
|   this->command(SSD1325_SETVSL);        // set Low Voltage Level of SEG Pin | ||||
|   this->command(0x0D | 0x02); | ||||
|   this->command(SSD1325_NORMALDISPLAY); /* set display mode */ | ||||
|   this->command(SSD1325_DISPLAYON);     /* display ON */ | ||||
| } | ||||
| void SSD1325::display() { | ||||
|   this->command(SSD1325_SETCOLADDR); /* set column address */ | ||||
|   this->command(0x00);               /* set column start address */ | ||||
|   this->command(0x3F);               /* set column end address */ | ||||
|   this->command(SSD1325_SETROWADDR); /* set row address */ | ||||
|   this->command(0x00);               /* set row start address */ | ||||
|   this->command(0x3F);               /* set row end address */ | ||||
|  | ||||
|   this->write_display_data(); | ||||
| } | ||||
| void SSD1325::update() { | ||||
|   this->do_update_(); | ||||
|   this->display(); | ||||
| } | ||||
| int SSD1325::get_height_internal() { | ||||
|   switch (this->model_) { | ||||
|     case SSD1325_MODEL_128_32: | ||||
|       return 32; | ||||
|     case SSD1325_MODEL_128_64: | ||||
|       return 64; | ||||
|     case SSD1325_MODEL_96_16: | ||||
|       return 16; | ||||
|     case SSD1325_MODEL_64_48: | ||||
|       return 48; | ||||
|     default: | ||||
|       return 0; | ||||
|   } | ||||
| } | ||||
| int SSD1325::get_width_internal() { | ||||
|   switch (this->model_) { | ||||
|     case SSD1325_MODEL_128_32: | ||||
|     case SSD1325_MODEL_128_64: | ||||
|       return 128; | ||||
|     case SSD1325_MODEL_96_16: | ||||
|       return 96; | ||||
|     case SSD1325_MODEL_64_48: | ||||
|       return 64; | ||||
|     default: | ||||
|       return 0; | ||||
|   } | ||||
| } | ||||
| size_t SSD1325::get_buffer_length_() { | ||||
|   return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 8u; | ||||
| } | ||||
|  | ||||
| void HOT SSD1325::draw_absolute_pixel_internal(int x, int y, int color) { | ||||
|   if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) | ||||
|     return; | ||||
|  | ||||
|   uint16_t pos = x + (y / 8) * this->get_width_internal(); | ||||
|   uint8_t subpos = y % 8; | ||||
|   if (color) { | ||||
|     this->buffer_[pos] |= (1 << subpos); | ||||
|   } else { | ||||
|     this->buffer_[pos] &= ~(1 << subpos); | ||||
|   } | ||||
| } | ||||
| void SSD1325::fill(int color) { | ||||
|   uint8_t fill = color ? 0xFF : 0x00; | ||||
|   for (uint32_t i = 0; i < this->get_buffer_length_(); i++) | ||||
|     this->buffer_[i] = fill; | ||||
| } | ||||
| void SSD1325::init_reset_() { | ||||
|   if (this->reset_pin_ != nullptr) { | ||||
|     this->reset_pin_->setup(); | ||||
|     this->reset_pin_->digital_write(true); | ||||
|     delay(1); | ||||
|     // Trigger Reset | ||||
|     this->reset_pin_->digital_write(false); | ||||
|     delay(10); | ||||
|     // Wake up | ||||
|     this->reset_pin_->digital_write(true); | ||||
|   } | ||||
| } | ||||
| const char *SSD1325::model_str_() { | ||||
|   switch (this->model_) { | ||||
|     case SSD1325_MODEL_128_32: | ||||
|       return "SSD1325 128x32"; | ||||
|     case SSD1325_MODEL_128_64: | ||||
|       return "SSD1325 128x64"; | ||||
|     case SSD1325_MODEL_96_16: | ||||
|       return "SSD1325 96x16"; | ||||
|     case SSD1325_MODEL_64_48: | ||||
|       return "SSD1325 64x48"; | ||||
|     default: | ||||
|       return "Unknown"; | ||||
|   } | ||||
| } | ||||
|  | ||||
| }  // namespace ssd1325_base | ||||
| }  // namespace esphome | ||||
							
								
								
									
										50
									
								
								esphome/components/ssd1325_base/ssd1325_base.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								esphome/components/ssd1325_base/ssd1325_base.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/esphal.h" | ||||
| #include "esphome/components/display/display_buffer.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace ssd1325_base { | ||||
|  | ||||
| enum SSD1325Model { | ||||
|   SSD1325_MODEL_128_32 = 0, | ||||
|   SSD1325_MODEL_128_64, | ||||
|   SSD1325_MODEL_96_16, | ||||
|   SSD1325_MODEL_64_48, | ||||
| }; | ||||
|  | ||||
| class SSD1325 : public PollingComponent, public display::DisplayBuffer { | ||||
|  public: | ||||
|   void setup() override; | ||||
|  | ||||
|   void display(); | ||||
|  | ||||
|   void update() override; | ||||
|  | ||||
|   void set_model(SSD1325Model model) { this->model_ = model; } | ||||
|   void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } | ||||
|   void set_external_vcc(bool external_vcc) { this->external_vcc_ = external_vcc; } | ||||
|  | ||||
|   float get_setup_priority() const override { return setup_priority::PROCESSOR; } | ||||
|   void fill(int color) override; | ||||
|  | ||||
|  protected: | ||||
|   virtual void command(uint8_t value) = 0; | ||||
|   virtual void write_display_data() = 0; | ||||
|   void init_reset_(); | ||||
|  | ||||
|   void draw_absolute_pixel_internal(int x, int y, int color) override; | ||||
|  | ||||
|   int get_height_internal() override; | ||||
|   int get_width_internal() override; | ||||
|   size_t get_buffer_length_(); | ||||
|   const char *model_str_(); | ||||
|  | ||||
|   SSD1325Model model_{SSD1325_MODEL_128_64}; | ||||
|   GPIOPin *reset_pin_{nullptr}; | ||||
|   bool external_vcc_{false}; | ||||
| }; | ||||
|  | ||||
| }  // namespace ssd1325_base | ||||
| }  // namespace esphome | ||||
							
								
								
									
										0
									
								
								esphome/components/ssd1325_spi/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/ssd1325_spi/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										26
									
								
								esphome/components/ssd1325_spi/display.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								esphome/components/ssd1325_spi/display.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import spi, ssd1325_base | ||||
| from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES | ||||
|  | ||||
| AUTO_LOAD = ['ssd1325_base'] | ||||
| DEPENDENCIES = ['spi'] | ||||
|  | ||||
| ssd1325_spi = cg.esphome_ns.namespace('ssd1325_spi') | ||||
| SPISSD1325 = ssd1325_spi.class_('SPISSD1325', ssd1325_base.SSD1325, spi.SPIDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(ssd1325_base.SSD1325_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(SPISSD1325), | ||||
|     cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(spi.SPI_DEVICE_SCHEMA), | ||||
|                        cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield ssd1325_base.setup_ssd1036(var, config) | ||||
|     yield spi.register_spi_device(var, config) | ||||
|  | ||||
|     dc = yield cg.gpio_pin_expression(config[CONF_DC_PIN]) | ||||
|     cg.add(var.set_dc_pin(dc)) | ||||
							
								
								
									
										64
									
								
								esphome/components/ssd1325_spi/ssd1325_spi.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								esphome/components/ssd1325_spi/ssd1325_spi.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| #include "ssd1325_spi.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace ssd1325_spi { | ||||
|  | ||||
| static const char *TAG = "ssd1325_spi"; | ||||
|  | ||||
| void SPISSD1325::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up SPI SSD1325..."); | ||||
|   this->spi_setup(); | ||||
|   this->dc_pin_->setup();  // OUTPUT | ||||
|   this->cs_->setup();      // OUTPUT | ||||
|  | ||||
|   this->init_reset_(); | ||||
|   delay(500); | ||||
|   SSD1325::setup(); | ||||
| } | ||||
| void SPISSD1325::dump_config() { | ||||
|   LOG_DISPLAY("", "SPI SSD1325", this); | ||||
|   ESP_LOGCONFIG(TAG, "  Model: %s", this->model_str_()); | ||||
|   LOG_PIN("  CS Pin: ", this->cs_); | ||||
|   LOG_PIN("  DC Pin: ", this->dc_pin_); | ||||
|   LOG_PIN("  Reset Pin: ", this->reset_pin_); | ||||
|   ESP_LOGCONFIG(TAG, "  External VCC: %s", YESNO(this->external_vcc_)); | ||||
|   LOG_UPDATE_INTERVAL(this); | ||||
| } | ||||
| void SPISSD1325::command(uint8_t value) { | ||||
|   this->cs_->digital_write(true); | ||||
|   this->dc_pin_->digital_write(false); | ||||
|   delay(1); | ||||
|   this->enable(); | ||||
|   this->cs_->digital_write(false); | ||||
|   this->write_byte(value); | ||||
|   this->cs_->digital_write(true); | ||||
|   this->disable(); | ||||
| } | ||||
| void HOT SPISSD1325::write_display_data() { | ||||
|   this->cs_->digital_write(true); | ||||
|   this->dc_pin_->digital_write(true); | ||||
|   this->cs_->digital_write(false); | ||||
|   delay(1); | ||||
|   this->enable(); | ||||
|   for (uint16_t x = 0; x < this->get_width_internal(); x += 2) { | ||||
|     for (uint16_t y = 0; y < this->get_height_internal(); y += 8) {  // we write 8 pixels at once | ||||
|       uint8_t left8 = this->buffer_[y * 16 + x]; | ||||
|       uint8_t right8 = this->buffer_[y * 16 + x + 1]; | ||||
|       for (uint8_t p = 0; p < 8; p++) { | ||||
|         uint8_t d = 0; | ||||
|         if (left8 & (1 << p)) | ||||
|           d |= 0xF0; | ||||
|         if (right8 & (1 << p)) | ||||
|           d |= 0x0F; | ||||
|         this->write_byte(d); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   this->cs_->digital_write(true); | ||||
|   this->disable(); | ||||
| } | ||||
|  | ||||
| }  // namespace ssd1325_spi | ||||
| }  // namespace esphome | ||||
							
								
								
									
										29
									
								
								esphome/components/ssd1325_spi/ssd1325_spi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								esphome/components/ssd1325_spi/ssd1325_spi.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/components/ssd1325_base/ssd1325_base.h" | ||||
| #include "esphome/components/spi/spi.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace ssd1325_spi { | ||||
|  | ||||
| class SPISSD1325 : public ssd1325_base::SSD1325, | ||||
|                    public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, spi::CLOCK_PHASE_TRAILING, | ||||
|                                          spi::DATA_RATE_8MHZ> { | ||||
|  public: | ||||
|   void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; } | ||||
|  | ||||
|   void setup() override; | ||||
|  | ||||
|   void dump_config() override; | ||||
|  | ||||
|  protected: | ||||
|   void command(uint8_t value) override; | ||||
|  | ||||
|   void write_display_data() override; | ||||
|  | ||||
|   GPIOPin *dc_pin_; | ||||
| }; | ||||
|  | ||||
| }  // namespace ssd1325_spi | ||||
| }  // namespace esphome | ||||
		Reference in New Issue
	
	Block a user