mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Max6956 support added (#3764)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -140,6 +140,7 @@ esphome/components/ltr390/* @sjtrny | |||||||
| esphome/components/matrix_keypad/* @ssieb | esphome/components/matrix_keypad/* @ssieb | ||||||
| esphome/components/max31865/* @DAVe3283 | esphome/components/max31865/* @DAVe3283 | ||||||
| esphome/components/max44009/* @berfenger | esphome/components/max44009/* @berfenger | ||||||
|  | esphome/components/max6956/* @looping40 | ||||||
| esphome/components/max7219digit/* @rspaargaren | esphome/components/max7219digit/* @rspaargaren | ||||||
| esphome/components/max9611/* @mckaymatthew | esphome/components/max9611/* @mckaymatthew | ||||||
| esphome/components/mcp23008/* @jesserockz | esphome/components/mcp23008/* @jesserockz | ||||||
|   | |||||||
							
								
								
									
										148
									
								
								esphome/components/max6956/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								esphome/components/max6956/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome import pins, automation | ||||||
|  | from esphome.components import i2c | ||||||
|  | from esphome.const import ( | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_NUMBER, | ||||||
|  |     CONF_MODE, | ||||||
|  |     CONF_INVERTED, | ||||||
|  |     CONF_INPUT, | ||||||
|  |     CONF_OUTPUT, | ||||||
|  |     CONF_PULLUP, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CODEOWNERS = ["@looping40"] | ||||||
|  |  | ||||||
|  | DEPENDENCIES = ["i2c"] | ||||||
|  | MULTI_CONF = True | ||||||
|  |  | ||||||
|  | CONF_BRIGHTNESS_MODE = "brightness_mode" | ||||||
|  | CONF_BRIGHTNESS_GLOBAL = "brightness_global" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | max6956_ns = cg.esphome_ns.namespace("max6956") | ||||||
|  |  | ||||||
|  | MAX6956 = max6956_ns.class_("MAX6956", cg.Component, i2c.I2CDevice) | ||||||
|  | MAX6956GPIOPin = max6956_ns.class_("MAX6956GPIOPin", cg.GPIOPin) | ||||||
|  |  | ||||||
|  | # Actions | ||||||
|  | SetCurrentGlobalAction = max6956_ns.class_("SetCurrentGlobalAction", automation.Action) | ||||||
|  | SetCurrentModeAction = max6956_ns.class_("SetCurrentModeAction", automation.Action) | ||||||
|  |  | ||||||
|  | MAX6956_CURRENTMODE = max6956_ns.enum("MAX6956CURRENTMODE") | ||||||
|  | CURRENT_MODES = { | ||||||
|  |     "global": MAX6956_CURRENTMODE.GLOBAL, | ||||||
|  |     "segment": MAX6956_CURRENTMODE.SEGMENT, | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = ( | ||||||
|  |     cv.Schema( | ||||||
|  |         { | ||||||
|  |             cv.Required(CONF_ID): cv.declare_id(MAX6956), | ||||||
|  |             cv.Optional(CONF_BRIGHTNESS_GLOBAL, default="0"): cv.int_range( | ||||||
|  |                 min=0, max=15 | ||||||
|  |             ), | ||||||
|  |             cv.Optional(CONF_BRIGHTNESS_MODE, default="global"): cv.enum( | ||||||
|  |                 CURRENT_MODES, lower=True | ||||||
|  |             ), | ||||||
|  |         } | ||||||
|  |     ) | ||||||
|  |     .extend(cv.COMPONENT_SCHEMA) | ||||||
|  |     .extend(i2c.i2c_device_schema(0x40)) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     await cg.register_component(var, config) | ||||||
|  |     await i2c.register_i2c_device(var, config) | ||||||
|  |     cg.add(var.set_brightness_mode(config[CONF_BRIGHTNESS_MODE])) | ||||||
|  |     cg.add(var.set_brightness_global(config[CONF_BRIGHTNESS_GLOBAL])) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_mode(value): | ||||||
|  |     if not (value[CONF_INPUT] or value[CONF_OUTPUT]): | ||||||
|  |         raise cv.Invalid("Mode must be either input or output") | ||||||
|  |     if value[CONF_INPUT] and value[CONF_OUTPUT]: | ||||||
|  |         raise cv.Invalid("Mode must be either input or output") | ||||||
|  |     if value[CONF_PULLUP] and not value[CONF_INPUT]: | ||||||
|  |         raise cv.Invalid("Pullup only available with input") | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CONF_MAX6956 = "max6956" | ||||||
|  |  | ||||||
|  | MAX6956_PIN_SCHEMA = cv.All( | ||||||
|  |     { | ||||||
|  |         cv.GenerateID(): cv.declare_id(MAX6956GPIOPin), | ||||||
|  |         cv.Required(CONF_MAX6956): cv.use_id(MAX6956), | ||||||
|  |         cv.Required(CONF_NUMBER): cv.int_range(min=4, max=31), | ||||||
|  |         cv.Optional(CONF_MODE, default={}): cv.All( | ||||||
|  |             { | ||||||
|  |                 cv.Optional(CONF_INPUT, default=False): cv.boolean, | ||||||
|  |                 cv.Optional(CONF_PULLUP, default=False): cv.boolean, | ||||||
|  |                 cv.Optional(CONF_OUTPUT, default=False): cv.boolean, | ||||||
|  |             }, | ||||||
|  |             validate_mode, | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_INVERTED, default=False): cv.boolean, | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pins.PIN_SCHEMA_REGISTRY.register(CONF_MAX6956, MAX6956_PIN_SCHEMA) | ||||||
|  | async def max6956_pin_to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     parent = await cg.get_variable(config[CONF_MAX6956]) | ||||||
|  |  | ||||||
|  |     cg.add(var.set_parent(parent)) | ||||||
|  |  | ||||||
|  |     num = config[CONF_NUMBER] | ||||||
|  |     cg.add(var.set_pin(num)) | ||||||
|  |     cg.add(var.set_inverted(config[CONF_INVERTED])) | ||||||
|  |     cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE]))) | ||||||
|  |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @automation.register_action( | ||||||
|  |     "max6956.set_brightness_global", | ||||||
|  |     SetCurrentGlobalAction, | ||||||
|  |     cv.maybe_simple_value( | ||||||
|  |         { | ||||||
|  |             cv.GenerateID(CONF_ID): cv.use_id(MAX6956), | ||||||
|  |             cv.Required(CONF_BRIGHTNESS_GLOBAL): cv.templatable( | ||||||
|  |                 cv.int_range(min=0, max=15) | ||||||
|  |             ), | ||||||
|  |         }, | ||||||
|  |         key=CONF_BRIGHTNESS_GLOBAL, | ||||||
|  |     ), | ||||||
|  | ) | ||||||
|  | async def max6956_set_brightness_global_to_code(config, action_id, template_arg, args): | ||||||
|  |     paren = await cg.get_variable(config[CONF_ID]) | ||||||
|  |     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||||
|  |     template_ = await cg.templatable(config[CONF_BRIGHTNESS_GLOBAL], args, float) | ||||||
|  |     cg.add(var.set_brightness_global(template_)) | ||||||
|  |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @automation.register_action( | ||||||
|  |     "max6956.set_brightness_mode", | ||||||
|  |     SetCurrentModeAction, | ||||||
|  |     cv.maybe_simple_value( | ||||||
|  |         { | ||||||
|  |             cv.Required(CONF_ID): cv.use_id(MAX6956), | ||||||
|  |             cv.Required(CONF_BRIGHTNESS_MODE): cv.templatable( | ||||||
|  |                 cv.enum(CURRENT_MODES, lower=True) | ||||||
|  |             ), | ||||||
|  |         }, | ||||||
|  |         key=CONF_BRIGHTNESS_MODE, | ||||||
|  |     ), | ||||||
|  | ) | ||||||
|  | async def max6956_set_brightness_mode_to_code(config, action_id, template_arg, args): | ||||||
|  |     paren = await cg.get_variable(config[CONF_ID]) | ||||||
|  |     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||||
|  |     template_ = await cg.templatable(config[CONF_BRIGHTNESS_MODE], args, float) | ||||||
|  |     cg.add(var.set_brightness_mode(template_)) | ||||||
|  |     return var | ||||||
							
								
								
									
										40
									
								
								esphome/components/max6956/automation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								esphome/components/max6956/automation.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/automation.h" | ||||||
|  | #include "esphome/components/max6956/max6956.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace max6956 { | ||||||
|  |  | ||||||
|  | template<typename... Ts> class SetCurrentGlobalAction : public Action<Ts...> { | ||||||
|  |  public: | ||||||
|  |   SetCurrentGlobalAction(MAX6956 *max6956) : max6956_(max6956) {} | ||||||
|  |  | ||||||
|  |   TEMPLATABLE_VALUE(uint8_t, brightness_global) | ||||||
|  |  | ||||||
|  |   void play(Ts... x) override { | ||||||
|  |     this->max6956_->set_brightness_global(this->brightness_global_.value(x...)); | ||||||
|  |     this->max6956_->write_brightness_global(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   MAX6956 *max6956_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<typename... Ts> class SetCurrentModeAction : public Action<Ts...> { | ||||||
|  |  public: | ||||||
|  |   SetCurrentModeAction(MAX6956 *max6956) : max6956_(max6956) {} | ||||||
|  |  | ||||||
|  |   TEMPLATABLE_VALUE(max6956::MAX6956CURRENTMODE, brightness_mode) | ||||||
|  |  | ||||||
|  |   void play(Ts... x) override { | ||||||
|  |     this->max6956_->set_brightness_mode(this->brightness_mode_.value(x...)); | ||||||
|  |     this->max6956_->write_brightness_mode(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   MAX6956 *max6956_; | ||||||
|  | }; | ||||||
|  | }  // namespace max6956 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										170
									
								
								esphome/components/max6956/max6956.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								esphome/components/max6956/max6956.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | |||||||
|  | #include "max6956.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace max6956 { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "max6956"; | ||||||
|  |  | ||||||
|  | /// Masks for MAX6956 Configuration register | ||||||
|  | const uint32_t MASK_TRANSITION_DETECTION = 0x80; | ||||||
|  | const uint32_t MASK_INDIVIDUAL_CURRENT = 0x40; | ||||||
|  | const uint32_t MASK_NORMAL_OPERATION = 0x01; | ||||||
|  |  | ||||||
|  | const uint32_t MASK_1PORT_VALUE = 0x03; | ||||||
|  | const uint32_t MASK_PORT_CONFIG = 0x03; | ||||||
|  | const uint8_t MASK_CONFIG_CURRENT = 0x40; | ||||||
|  | const uint8_t MASK_CURRENT_PIN = 0x0F; | ||||||
|  |  | ||||||
|  | /************************************** | ||||||
|  |  *    MAX6956                         * | ||||||
|  |  **************************************/ | ||||||
|  | void MAX6956::setup() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "Setting up MAX6956..."); | ||||||
|  |   uint8_t configuration; | ||||||
|  |   if (!this->read_reg_(MAX6956_CONFIGURATION, &configuration)) { | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   write_brightness_global(); | ||||||
|  |   write_brightness_mode(); | ||||||
|  |  | ||||||
|  |   /** TO DO : read transition detection in yaml | ||||||
|  |       TO DO : read indivdual current in yaml **/ | ||||||
|  |   this->read_reg_(MAX6956_CONFIGURATION, &configuration); | ||||||
|  |   ESP_LOGD(TAG, "Initial reg[0x%.2X]=0x%.2X", MAX6956_CONFIGURATION, configuration); | ||||||
|  |   configuration = configuration | MASK_NORMAL_OPERATION; | ||||||
|  |   this->write_reg_(MAX6956_CONFIGURATION, configuration); | ||||||
|  |  | ||||||
|  |   ESP_LOGCONFIG(TAG, "Enabling normal operation"); | ||||||
|  |   ESP_LOGD(TAG, "setup reg[0x%.2X]=0x%.2X", MAX6956_CONFIGURATION, configuration); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool MAX6956::digital_read(uint8_t pin) { | ||||||
|  |   uint8_t reg_addr = MAX6956_1PORT_VALUE_START + pin; | ||||||
|  |   uint8_t value = 0; | ||||||
|  |   this->read_reg_(reg_addr, &value); | ||||||
|  |   return (value & MASK_1PORT_VALUE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956::digital_write(uint8_t pin, bool value) { | ||||||
|  |   uint8_t reg_addr = MAX6956_1PORT_VALUE_START + pin; | ||||||
|  |   this->write_reg_(reg_addr, value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956::pin_mode(uint8_t pin, gpio::Flags flags) { | ||||||
|  |   uint8_t reg_addr = MAX6956_PORT_CONFIG_START + (pin - MAX6956_MIN) / 4; | ||||||
|  |   uint8_t config = 0; | ||||||
|  |   uint8_t shift = 2 * (pin % 4); | ||||||
|  |   MAX6956GPIOMode mode = MAX6956_INPUT; | ||||||
|  |  | ||||||
|  |   if (flags == gpio::FLAG_INPUT) { | ||||||
|  |     mode = MAX6956GPIOMode::MAX6956_INPUT; | ||||||
|  |   } else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) { | ||||||
|  |     mode = MAX6956GPIOMode::MAX6956_INPUT_PULLUP; | ||||||
|  |   } else if (flags == gpio::FLAG_OUTPUT) { | ||||||
|  |     mode = MAX6956GPIOMode::MAX6956_OUTPUT; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this->read_reg_(reg_addr, &config); | ||||||
|  |   config &= ~(MASK_PORT_CONFIG << shift); | ||||||
|  |   config |= (mode << shift); | ||||||
|  |   this->write_reg_(reg_addr, config); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956::pin_mode(uint8_t pin, max6956::MAX6956GPIOFlag flags) { | ||||||
|  |   uint8_t reg_addr = MAX6956_PORT_CONFIG_START + (pin - MAX6956_MIN) / 4; | ||||||
|  |   uint8_t config = 0; | ||||||
|  |   uint8_t shift = 2 * (pin % 4); | ||||||
|  |   MAX6956GPIOMode mode = MAX6956GPIOMode::MAX6956_LED; | ||||||
|  |  | ||||||
|  |   if (flags == max6956::FLAG_LED) { | ||||||
|  |     mode = MAX6956GPIOMode::MAX6956_LED; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this->read_reg_(reg_addr, &config); | ||||||
|  |   config &= ~(MASK_PORT_CONFIG << shift); | ||||||
|  |   config |= (mode << shift); | ||||||
|  |   this->write_reg_(reg_addr, config); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956::set_brightness_global(uint8_t current) { | ||||||
|  |   if (current > 15) { | ||||||
|  |     ESP_LOGE(TAG, "Global brightness out off range (%u)", current); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   global_brightness_ = current; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956::write_brightness_global() { this->write_reg_(MAX6956_GLOBAL_CURRENT, global_brightness_); } | ||||||
|  |  | ||||||
|  | void MAX6956::set_brightness_mode(max6956::MAX6956CURRENTMODE brightness_mode) { brightness_mode_ = brightness_mode; }; | ||||||
|  |  | ||||||
|  | void MAX6956::write_brightness_mode() { | ||||||
|  |   uint8_t reg_addr = MAX6956_CONFIGURATION; | ||||||
|  |   uint8_t config = 0; | ||||||
|  |  | ||||||
|  |   this->read_reg_(reg_addr, &config); | ||||||
|  |   config &= ~MASK_CONFIG_CURRENT; | ||||||
|  |   config |= brightness_mode_ << 6; | ||||||
|  |   this->write_reg_(reg_addr, config); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956::set_pin_brightness(uint8_t pin, float brightness) { | ||||||
|  |   uint8_t reg_addr = MAX6956_CURRENT_START + (pin - MAX6956_MIN) / 2; | ||||||
|  |   uint8_t config = 0; | ||||||
|  |   uint8_t shift = 4 * (pin % 2); | ||||||
|  |   uint8_t bright = roundf(brightness * 15); | ||||||
|  |  | ||||||
|  |   if (prev_bright_[pin - MAX6956_MIN] == bright) | ||||||
|  |     return; | ||||||
|  |  | ||||||
|  |   prev_bright_[pin - MAX6956_MIN] = bright; | ||||||
|  |  | ||||||
|  |   this->read_reg_(reg_addr, &config); | ||||||
|  |   config &= ~(MASK_CURRENT_PIN << shift); | ||||||
|  |   config |= (bright << shift); | ||||||
|  |   this->write_reg_(reg_addr, config); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool MAX6956::read_reg_(uint8_t reg, uint8_t *value) { | ||||||
|  |   if (this->is_failed()) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   return this->read_byte(reg, value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool MAX6956::write_reg_(uint8_t reg, uint8_t value) { | ||||||
|  |   if (this->is_failed()) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   return this->write_byte(reg, value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "MAX6956"); | ||||||
|  |  | ||||||
|  |   if (brightness_mode_ == MAX6956CURRENTMODE::GLOBAL) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "current mode: global"); | ||||||
|  |     ESP_LOGCONFIG(TAG, "global brightness: %u", global_brightness_); | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGCONFIG(TAG, "current mode: segment"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /************************************** | ||||||
|  |  *    MAX6956GPIOPin                  * | ||||||
|  |  **************************************/ | ||||||
|  | void MAX6956GPIOPin::setup() { pin_mode(flags_); } | ||||||
|  | void MAX6956GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } | ||||||
|  | bool MAX6956GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } | ||||||
|  | void MAX6956GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } | ||||||
|  | std::string MAX6956GPIOPin::dump_summary() const { | ||||||
|  |   char buffer[32]; | ||||||
|  |   snprintf(buffer, sizeof(buffer), "%u via Max6956", pin_); | ||||||
|  |   return buffer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace max6956 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										94
									
								
								esphome/components/max6956/max6956.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								esphome/components/max6956/max6956.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/hal.h" | ||||||
|  | #include "esphome/components/i2c/i2c.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace max6956 { | ||||||
|  |  | ||||||
|  | /// Modes for MAX6956 pins | ||||||
|  | enum MAX6956GPIOMode : uint8_t { | ||||||
|  |   MAX6956_LED = 0x00, | ||||||
|  |   MAX6956_OUTPUT = 0x01, | ||||||
|  |   MAX6956_INPUT = 0x02, | ||||||
|  |   MAX6956_INPUT_PULLUP = 0x03 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Range for MAX6956 pins | ||||||
|  | enum MAX6956GPIORange : uint8_t { | ||||||
|  |   MAX6956_MIN = 4, | ||||||
|  |   MAX6956_MAX = 31, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum MAX6956GPIORegisters { | ||||||
|  |   MAX6956_GLOBAL_CURRENT = 0x02, | ||||||
|  |   MAX6956_CONFIGURATION = 0x04, | ||||||
|  |   MAX6956_TRANSITION_DETECT_MASK = 0x06, | ||||||
|  |   MAX6956_DISPLAY_TEST = 0x07, | ||||||
|  |   MAX6956_PORT_CONFIG_START = 0x09,   // Port Configuration P7, P6, P5, P4 | ||||||
|  |   MAX6956_CURRENT_START = 0x12,       // Current054 | ||||||
|  |   MAX6956_1PORT_VALUE_START = 0x20,   // Port 0 only (virtual port, no action) | ||||||
|  |   MAX6956_8PORTS_VALUE_START = 0x44,  // 8 ports 4–11 (data bits D0–D7) | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum MAX6956GPIOFlag { FLAG_LED = 0x20 }; | ||||||
|  |  | ||||||
|  | enum MAX6956CURRENTMODE { GLOBAL = 0x00, SEGMENT = 0x01 }; | ||||||
|  |  | ||||||
|  | class MAX6956 : public Component, public i2c::I2CDevice { | ||||||
|  |  public: | ||||||
|  |   MAX6956() = default; | ||||||
|  |  | ||||||
|  |   void setup() override; | ||||||
|  |  | ||||||
|  |   bool digital_read(uint8_t pin); | ||||||
|  |   void digital_write(uint8_t pin, bool value); | ||||||
|  |   void pin_mode(uint8_t pin, gpio::Flags flags); | ||||||
|  |   void pin_mode(uint8_t pin, max6956::MAX6956GPIOFlag flags); | ||||||
|  |  | ||||||
|  |   float get_setup_priority() const override { return setup_priority::HARDWARE; } | ||||||
|  |  | ||||||
|  |   void set_brightness_global(uint8_t current); | ||||||
|  |   void set_brightness_mode(max6956::MAX6956CURRENTMODE brightness_mode); | ||||||
|  |   void set_pin_brightness(uint8_t pin, float brightness); | ||||||
|  |  | ||||||
|  |   void dump_config() override; | ||||||
|  |  | ||||||
|  |   void write_brightness_global(); | ||||||
|  |   void write_brightness_mode(); | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   // read a given register | ||||||
|  |   bool read_reg_(uint8_t reg, uint8_t *value); | ||||||
|  |   // write a value to a given register | ||||||
|  |   bool write_reg_(uint8_t reg, uint8_t value); | ||||||
|  |   max6956::MAX6956CURRENTMODE brightness_mode_; | ||||||
|  |   uint8_t global_brightness_; | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   int8_t prev_bright_[28] = {0}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class MAX6956GPIOPin : public GPIOPin { | ||||||
|  |  public: | ||||||
|  |   void setup() override; | ||||||
|  |   void pin_mode(gpio::Flags flags) override; | ||||||
|  |   bool digital_read() override; | ||||||
|  |   void digital_write(bool value) override; | ||||||
|  |   std::string dump_summary() const override; | ||||||
|  |  | ||||||
|  |   void set_parent(MAX6956 *parent) { parent_ = parent; } | ||||||
|  |   void set_pin(uint8_t pin) { pin_ = pin; } | ||||||
|  |   void set_inverted(bool inverted) { inverted_ = inverted; } | ||||||
|  |   void set_flags(gpio::Flags flags) { flags_ = flags; } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   MAX6956 *parent_; | ||||||
|  |   uint8_t pin_; | ||||||
|  |   bool inverted_; | ||||||
|  |   gpio::Flags flags_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace max6956 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										28
									
								
								esphome/components/max6956/output/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								esphome/components/max6956/output/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.components import output | ||||||
|  | from esphome.const import CONF_PIN, CONF_ID | ||||||
|  | from .. import MAX6956, max6956_ns, CONF_MAX6956 | ||||||
|  |  | ||||||
|  | DEPENDENCIES = ["max6956"] | ||||||
|  |  | ||||||
|  | MAX6956LedChannel = max6956_ns.class_( | ||||||
|  |     "MAX6956LedChannel", output.FloatOutput, cg.Component | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( | ||||||
|  |     { | ||||||
|  |         cv.Required(CONF_ID): cv.declare_id(MAX6956LedChannel), | ||||||
|  |         cv.GenerateID(CONF_MAX6956): cv.use_id(MAX6956), | ||||||
|  |         cv.Required(CONF_PIN): cv.int_range(min=4, max=31), | ||||||
|  |     } | ||||||
|  | ).extend(cv.COMPONENT_SCHEMA) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     parent = await cg.get_variable(config[CONF_MAX6956]) | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     await cg.register_component(var, config) | ||||||
|  |     await output.register_output(var, config) | ||||||
|  |     cg.add(var.set_pin(config[CONF_PIN])) | ||||||
|  |     cg.add(var.set_parent(parent)) | ||||||
							
								
								
									
										26
									
								
								esphome/components/max6956/output/max6956_led_output.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								esphome/components/max6956/output/max6956_led_output.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | #include "max6956_led_output.h" | ||||||
|  | #include "esphome/core/helpers.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace max6956 { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "max6956_led_channel"; | ||||||
|  |  | ||||||
|  | void MAX6956LedChannel::write_state(float state) { this->parent_->set_pin_brightness(this->pin_, state); } | ||||||
|  |  | ||||||
|  | void MAX6956LedChannel::write_state(bool state) { this->parent_->digital_write(this->pin_, state); } | ||||||
|  |  | ||||||
|  | void MAX6956LedChannel::setup() { | ||||||
|  |   this->parent_->pin_mode(this->pin_, max6956::FLAG_LED); | ||||||
|  |   this->turn_off(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MAX6956LedChannel::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "MAX6956 current:"); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  MAX6956 pin: %d", this->pin_); | ||||||
|  |   LOG_FLOAT_OUTPUT(this); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace max6956 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										28
									
								
								esphome/components/max6956/output/max6956_led_output.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								esphome/components/max6956/output/max6956_led_output.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/max6956/max6956.h" | ||||||
|  | #include "esphome/components/output/float_output.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace max6956 { | ||||||
|  |  | ||||||
|  | class MAX6956; | ||||||
|  |  | ||||||
|  | class MAX6956LedChannel : public output::FloatOutput, public Component { | ||||||
|  |  public: | ||||||
|  |   void set_parent(MAX6956 *parent) { this->parent_ = parent; } | ||||||
|  |   void set_pin(uint8_t pin) { pin_ = pin; } | ||||||
|  |   void setup() override; | ||||||
|  |   void dump_config() override; | ||||||
|  |   float get_setup_priority() const override { return setup_priority::HARDWARE; } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void write_state(float state) override; | ||||||
|  |   void write_state(bool state) override; | ||||||
|  |  | ||||||
|  |   MAX6956 *parent_; | ||||||
|  |   uint8_t pin_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace max6956 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -374,6 +374,16 @@ binary_sensor: | |||||||
|     on_press: |     on_press: | ||||||
|       - logger.log: Touched |       - logger.log: Touched | ||||||
|  |  | ||||||
|  |   - platform: gpio | ||||||
|  |     name: MaxIn Pin 4 | ||||||
|  |     pin: | ||||||
|  |       max6956: max6956_1 | ||||||
|  |       number: 4 | ||||||
|  |       mode: | ||||||
|  |         input: true | ||||||
|  |         pullup: true | ||||||
|  |       inverted: false | ||||||
|  |  | ||||||
| climate: | climate: | ||||||
|   - platform: tuya |   - platform: tuya | ||||||
|     id: tuya_climate |     id: tuya_climate | ||||||
| @@ -716,3 +726,7 @@ voice_assistant: | |||||||
|     - logger.log: |     - logger.log: | ||||||
|         format: "Voice assistant error - code %s, message: %s" |         format: "Voice assistant error - code %s, message: %s" | ||||||
|         args: [code.c_str(), message.c_str()] |         args: [code.c_str(), message.c_str()] | ||||||
|  |  | ||||||
|  | max6956: | ||||||
|  |   - id: max6956_1 | ||||||
|  |     address: 0x40 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user