#include "matrix_keypad.h" #include "esphome/core/log.h" #include "esphome/core/application.h" namespace esphome { namespace matrix_keypad { static const char *const TAG = "matrix_keypad"; void MatrixKeypad::setup() { for (auto *pin : this->rows_) { pin->setup(); if (!has_diodes_) { pin->pin_mode(gpio::FLAG_INPUT); } else { pin->digital_write(!has_pulldowns_); } } for (auto *pin : this->columns_) { pin->setup(); if (has_pulldowns_) { pin->pin_mode(gpio::FLAG_INPUT); } else { pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); } } } void MatrixKeypad::loop() { static uint32_t active_start = 0; static int active_key = -1; uint32_t now = App.get_loop_component_start_time(); int key = -1; bool error = false; int pos = 0, row, col; for (auto *row : this->rows_) { if (!has_diodes_) row->pin_mode(gpio::FLAG_OUTPUT); row->digital_write(has_pulldowns_); for (auto *col : this->columns_) { if (col->digital_read() == has_pulldowns_) { if (key != -1) { error = true; } else { key = pos; } } pos++; } row->digital_write(!has_pulldowns_); if (!has_diodes_) row->pin_mode(gpio::FLAG_INPUT); } if (error) return; if (key != active_key) { if ((active_key != -1) && (this->pressed_key_ == active_key)) { row = this->pressed_key_ / this->columns_.size(); col = this->pressed_key_ % this->columns_.size(); ESP_LOGD(TAG, "key @ row %d, col %d released", row, col); for (auto &listener : this->listeners_) listener->button_released(row, col); if (!this->keys_.empty()) { uint8_t keycode = this->keys_[this->pressed_key_]; ESP_LOGD(TAG, "key '%c' released", keycode); for (auto &listener : this->listeners_) listener->key_released(keycode); } this->pressed_key_ = -1; } active_key = key; if (key == -1) return; active_start = now; } if ((this->pressed_key_ == key) || (now - active_start < this->debounce_time_)) return; row = key / this->columns_.size(); col = key % this->columns_.size(); ESP_LOGD(TAG, "key @ row %d, col %d pressed", row, col); for (auto &listener : this->listeners_) listener->button_pressed(row, col); if (!this->keys_.empty()) { uint8_t keycode = this->keys_[key]; ESP_LOGD(TAG, "key '%c' pressed", keycode); for (auto &trigger : this->key_triggers_) trigger->trigger(keycode); for (auto &listener : this->listeners_) listener->key_pressed(keycode); this->send_key_(keycode); } this->pressed_key_ = key; } void MatrixKeypad::dump_config() { ESP_LOGCONFIG(TAG, "Matrix Keypad:\n" " Rows:"); for (auto &pin : this->rows_) { LOG_PIN(" Pin: ", pin); } ESP_LOGCONFIG(TAG, " Cols:"); for (auto &pin : this->columns_) { LOG_PIN(" Pin: ", pin); } } void MatrixKeypad::register_listener(MatrixKeypadListener *listener) { this->listeners_.push_back(listener); } void MatrixKeypad::register_key_trigger(MatrixKeyTrigger *trig) { this->key_triggers_.push_back(trig); } } // namespace matrix_keypad } // namespace esphome