mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 06:33:51 +00:00 
			
		
		
		
	Tm1637 binarysensor (#2792)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							2e436eae6b
						
					
				
				
					commit
					70fafa473b
				
			
							
								
								
									
										26
									
								
								esphome/components/tm1637/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								esphome/components/tm1637/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import binary_sensor | ||||
| from esphome.const import CONF_ID, CONF_KEY | ||||
|  | ||||
| CONF_TM1637_ID = "tm1637_id" | ||||
|  | ||||
| tm1637_ns = cg.esphome_ns.namespace("tm1637") | ||||
| TM1637Display = tm1637_ns.class_("TM1637Display", cg.PollingComponent) | ||||
| TM1637Key = tm1637_ns.class_("TM1637Key", binary_sensor.BinarySensor) | ||||
|  | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(TM1637Key), | ||||
|         cv.GenerateID(CONF_TM1637_ID): cv.use_id(TM1637Display), | ||||
|         cv.Required(CONF_KEY): cv.int_range(min=0, max=15), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     await binary_sensor.register_binary_sensor(var, config) | ||||
|     cg.add(var.set_keycode(config[CONF_KEY])) | ||||
|     hub = await cg.get_variable(config[CONF_TM1637_ID]) | ||||
|     cg.add(hub.add_tm1637_key(var)) | ||||
| @@ -7,11 +7,17 @@ namespace esphome { | ||||
| namespace tm1637 { | ||||
|  | ||||
| static const char *const TAG = "display.tm1637"; | ||||
| const uint8_t TM1637_I2C_COMM1 = 0x40; | ||||
| const uint8_t TM1637_I2C_COMM2 = 0xC0; | ||||
| const uint8_t TM1637_I2C_COMM3 = 0x80; | ||||
| const uint8_t TM1637_CMD_DATA = 0x40;  //!< Display data command | ||||
| const uint8_t TM1637_CMD_CTRL = 0x80;  //!< Display control command | ||||
| const uint8_t TM1637_CMD_ADDR = 0xc0;  //!< Display address command | ||||
| const uint8_t TM1637_UNKNOWN_CHAR = 0b11111111; | ||||
|  | ||||
| // Data command bits | ||||
| const uint8_t TM1637_DATA_WRITE = 0x00;          //!< Write data | ||||
| const uint8_t TM1637_DATA_READ_KEYS = 0x02;      //!< Read keys | ||||
| const uint8_t TM1637_DATA_AUTO_INC_ADDR = 0x00;  //!< Auto increment address | ||||
| const uint8_t TM1637_DATA_FIXED_ADDR = 0x04;     //!< Fixed address | ||||
|  | ||||
| // | ||||
| //      A | ||||
| //     --- | ||||
| @@ -138,6 +144,36 @@ void TM1637Display::dump_config() { | ||||
|   LOG_UPDATE_INTERVAL(this); | ||||
| } | ||||
|  | ||||
| #ifdef USE_BINARY_SENSOR | ||||
| void TM1637Display::loop() { | ||||
|   uint8_t val = this->get_keys(); | ||||
|   for (auto *tm1637_key : this->tm1637_keys_) | ||||
|     tm1637_key->process(val); | ||||
| } | ||||
|  | ||||
| uint8_t TM1637Display::get_keys() { | ||||
|   this->start_(); | ||||
|   this->send_byte_(TM1637_CMD_DATA | TM1637_DATA_READ_KEYS); | ||||
|   this->start_(); | ||||
|   uint8_t key_code = read_byte_(); | ||||
|   this->stop_(); | ||||
|   if (key_code != 0xFF) { | ||||
|     // Invert key_code: | ||||
|     //    Bit |  7  6  5  4  3  2  1  0 | ||||
|     //  ------+------------------------- | ||||
|     //   From | S0 S1 S2 K1 K2 1  1  1 | ||||
|     //     To | S0 S1 S2 K1 K2 0  0  0 | ||||
|     key_code = ~key_code; | ||||
|     // Shift bits to: | ||||
|     //    Bit | 7  6  5  4  3  2  1  0 | ||||
|     //  ------+------------------------ | ||||
|     //     To | 0  0  0  0  K2 S2 S1 S0 | ||||
|     key_code = (uint8_t)((key_code & 0x80) >> 7 | (key_code & 0x40) >> 5 | (key_code & 0x20) >> 3 | (key_code & 0x08)); | ||||
|   } | ||||
|   return key_code; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void TM1637Display::update() { | ||||
|   for (uint8_t &i : this->buffer_) | ||||
|     i = 0; | ||||
| @@ -165,14 +201,14 @@ void TM1637Display::stop_() { | ||||
| void TM1637Display::display() { | ||||
|   ESP_LOGVV(TAG, "Display %02X%02X%02X%02X", buffer_[0], buffer_[1], buffer_[2], buffer_[3]); | ||||
|  | ||||
|   // Write COMM1 | ||||
|   // Write DATA CMND | ||||
|   this->start_(); | ||||
|   this->send_byte_(TM1637_I2C_COMM1); | ||||
|   this->send_byte_(TM1637_CMD_DATA); | ||||
|   this->stop_(); | ||||
|  | ||||
|   // Write COMM2 + first digit address | ||||
|   // Write ADDR CMD + first digit address | ||||
|   this->start_(); | ||||
|   this->send_byte_(TM1637_I2C_COMM2); | ||||
|   this->send_byte_(TM1637_CMD_ADDR); | ||||
|  | ||||
|   // Write the data bytes | ||||
|   if (this->inverted_) { | ||||
| @@ -187,20 +223,17 @@ void TM1637Display::display() { | ||||
|  | ||||
|   this->stop_(); | ||||
|  | ||||
|   // Write COMM3 + brightness | ||||
|   // Write display CTRL CMND + brightness | ||||
|   this->start_(); | ||||
|   this->send_byte_(TM1637_I2C_COMM3 + ((this->intensity_ & 0x7) | 0x08)); | ||||
|   this->send_byte_(TM1637_CMD_CTRL + ((this->intensity_ & 0x7) | 0x08)); | ||||
|   this->stop_(); | ||||
| } | ||||
| bool TM1637Display::send_byte_(uint8_t b) { | ||||
|   uint8_t data = b; | ||||
|  | ||||
|   // 8 Data Bits | ||||
|   for (uint8_t i = 0; i < 8; i++) { | ||||
|     // CLK low | ||||
|     this->clk_pin_->pin_mode(gpio::FLAG_OUTPUT); | ||||
|     this->bit_delay_(); | ||||
|  | ||||
|     // Set data bit | ||||
|     if (data & 0x01) { | ||||
|       this->dio_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
| @@ -209,19 +242,16 @@ bool TM1637Display::send_byte_(uint8_t b) { | ||||
|     } | ||||
|  | ||||
|     this->bit_delay_(); | ||||
|  | ||||
|     // CLK high | ||||
|     this->clk_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
|     this->bit_delay_(); | ||||
|     data = data >> 1; | ||||
|   } | ||||
|  | ||||
|   // Wait for acknowledge | ||||
|   // CLK to zero | ||||
|   this->clk_pin_->pin_mode(gpio::FLAG_OUTPUT); | ||||
|   this->dio_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
|   this->bit_delay_(); | ||||
|  | ||||
|   // CLK to high | ||||
|   this->clk_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
|   this->bit_delay_(); | ||||
| @@ -237,8 +267,38 @@ bool TM1637Display::send_byte_(uint8_t b) { | ||||
|   return ack; | ||||
| } | ||||
|  | ||||
| uint8_t TM1637Display::read_byte_() { | ||||
|   uint8_t retval = 0; | ||||
|   // Prepare DIO to read data | ||||
|   this->dio_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
|   this->bit_delay_(); | ||||
|   // Data is shifted out by the TM1637 on the CLK falling edge | ||||
|   for (uint8_t bit = 0; bit < 8; bit++) { | ||||
|     this->clk_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
|     this->bit_delay_(); | ||||
|     // Read next bit | ||||
|     retval <<= 1; | ||||
|     if (this->dio_pin_->digital_read()) { | ||||
|       retval |= 0x01; | ||||
|     } | ||||
|     this->clk_pin_->pin_mode(gpio::FLAG_OUTPUT); | ||||
|     this->bit_delay_(); | ||||
|   } | ||||
|   // Return DIO to output mode | ||||
|   // Dummy ACK | ||||
|   this->dio_pin_->pin_mode(gpio::FLAG_OUTPUT); | ||||
|   this->bit_delay_(); | ||||
|   this->clk_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
|   this->bit_delay_(); | ||||
|   this->clk_pin_->pin_mode(gpio::FLAG_OUTPUT); | ||||
|   this->bit_delay_(); | ||||
|   this->dio_pin_->pin_mode(gpio::FLAG_INPUT); | ||||
|   this->bit_delay_(); | ||||
|   return retval; | ||||
| } | ||||
|  | ||||
| uint8_t TM1637Display::print(uint8_t start_pos, const char *str) { | ||||
|   ESP_LOGV(TAG, "Print at %d: %s", start_pos, str); | ||||
|   // ESP_LOGV(TAG, "Print at %d: %s", start_pos, str); | ||||
|   uint8_t pos = start_pos; | ||||
|   for (; *str != '\0'; str++) { | ||||
|     uint8_t data = TM1637_UNKNOWN_CHAR; | ||||
|   | ||||
| @@ -8,10 +8,17 @@ | ||||
| #include "esphome/components/time/real_time_clock.h" | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_BINARY_SENSOR | ||||
| #include "esphome/components/binary_sensor/binary_sensor.h" | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| namespace tm1637 { | ||||
|  | ||||
| class TM1637Display; | ||||
| #ifdef USE_BINARY_SENSOR | ||||
| class TM1637Key; | ||||
| #endif | ||||
|  | ||||
| using tm1637_writer_t = std::function<void(TM1637Display &)>; | ||||
|  | ||||
| @@ -46,10 +53,15 @@ class TM1637Display : public PollingComponent { | ||||
|  | ||||
|   void display(); | ||||
|  | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|   void loop() override; | ||||
|   uint8_t get_keys(); | ||||
|   void add_tm1637_key(TM1637Key *tm1637_key) { this->tm1637_keys_.push_back(tm1637_key); } | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_TIME | ||||
|   /// Evaluate the strftime-format and print the result at the given position. | ||||
|   uint8_t strftime(uint8_t pos, const char *format, time::ESPTime time) __attribute__((format(strftime, 3, 0))); | ||||
|  | ||||
|   /// Evaluate the strftime-format and print the result at position 0. | ||||
|   uint8_t strftime(const char *format, time::ESPTime time) __attribute__((format(strftime, 2, 0))); | ||||
| #endif | ||||
| @@ -58,6 +70,7 @@ class TM1637Display : public PollingComponent { | ||||
|   void bit_delay_(); | ||||
|   void setup_pins_(); | ||||
|   bool send_byte_(uint8_t b); | ||||
|   uint8_t read_byte_(); | ||||
|   void start_(); | ||||
|   void stop_(); | ||||
|  | ||||
| @@ -68,7 +81,23 @@ class TM1637Display : public PollingComponent { | ||||
|   bool inverted_; | ||||
|   optional<tm1637_writer_t> writer_{}; | ||||
|   uint8_t buffer_[6] = {0}; | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|   std::vector<TM1637Key *> tm1637_keys_{}; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| #ifdef USE_BINARY_SENSOR | ||||
| class TM1637Key : public binary_sensor::BinarySensor { | ||||
|   friend class TM1637Display; | ||||
|  | ||||
|  public: | ||||
|   void set_keycode(uint8_t key_code) { key_code_ = key_code; } | ||||
|   void process(uint8_t data) { this->publish_state(static_cast<bool>(data == this->key_code_)); } | ||||
|  | ||||
|  protected: | ||||
|   uint8_t key_code_{0}; | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| }  // namespace tm1637 | ||||
| }  // namespace esphome | ||||
|   | ||||
		Reference in New Issue
	
	Block a user