ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
mpr121.cpp
Go to the documentation of this file.
1#include "mpr121.h"
2
3#include <cstdint>
4
5#include "esphome/core/hal.h"
6#include "esphome/core/log.h"
7
8namespace esphome::mpr121 {
9
10static const char *const TAG = "mpr121";
11
13 this->disable_loop();
14 // soft reset device
15 this->write_byte(MPR121_SOFTRESET, 0x63);
16 this->set_timeout(100, [this]() {
17 if (!this->write_byte(MPR121_ECR, 0x0)) {
18 this->error_code_ = COMMUNICATION_FAILED;
19 this->mark_failed();
20 return;
21 }
22 // set touch sensitivity for all 12 channels
23 for (auto *channel : this->channels_) {
24 channel->setup();
25 }
26 this->write_byte(MPR121_MHDR, 0x01);
27 this->write_byte(MPR121_NHDR, 0x01);
28 this->write_byte(MPR121_NCLR, 0x0E);
29 this->write_byte(MPR121_FDLR, 0x00);
30
31 this->write_byte(MPR121_MHDF, 0x01);
32 this->write_byte(MPR121_NHDF, 0x05);
33 this->write_byte(MPR121_NCLF, 0x01);
34 this->write_byte(MPR121_FDLF, 0x00);
35
36 this->write_byte(MPR121_NHDT, 0x00);
37 this->write_byte(MPR121_NCLT, 0x00);
38 this->write_byte(MPR121_FDLT, 0x00);
39
41 // default, 16uA charge current
42 this->write_byte(MPR121_CONFIG1, 0x10);
43 // 0.5uS encoding, 1ms period
44 this->write_byte(MPR121_CONFIG2, 0x20);
45
46 // Write the Electrode Configuration Register
47 // * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits.
48 // * The 2 bits below is "Proximity Enable" and are left at 0.
49 // * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled
50 // as a range, starting at 0 up to the highest channel index used.
51 this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1));
52
53 this->flush_gpio_();
54 this->enable_loop();
55 });
56}
57
59 uint8_t mask = debounce << 4;
60 this->debounce_ &= 0x0f;
61 this->debounce_ |= mask;
62}
63
65 uint8_t mask = debounce & 0x0f;
66 this->debounce_ &= 0xf0;
67 this->debounce_ |= mask;
68};
69
71 ESP_LOGCONFIG(TAG, "MPR121:");
72 LOG_I2C_DEVICE(this);
73 switch (this->error_code_) {
75 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
76 break;
77 case NONE:
78 default:
79 break;
80 }
81}
83 uint16_t val = 0;
85
86 // Flip order
87 uint8_t lsb = val >> 8;
88 uint8_t msb = val;
89 val = (uint16_t(msb) << 8) | lsb;
90
91 for (auto *channel : this->channels_)
92 channel->process(val);
93
95}
96
97bool MPR121Component::digital_read(uint8_t ionum) { return (this->gpio_input_ & (1 << ionum)) != 0; }
98
99void MPR121Component::digital_write(uint8_t ionum, bool value) {
100 if (value) {
101 this->gpio_output_ |= (1 << ionum);
102 } else {
103 this->gpio_output_ &= ~(1 << ionum);
104 }
105 this->flush_gpio_();
106}
107
109 this->gpio_enable_ |= (1 << ionum);
110 if (flags & gpio::FLAG_INPUT) {
111 this->gpio_direction_ &= ~(1 << ionum);
112 } else if (flags & gpio::FLAG_OUTPUT) {
113 this->gpio_direction_ |= 1 << ionum;
114 }
115 this->flush_gpio_();
116}
117
119 if (this->is_failed()) {
120 return false;
121 }
122
123 // TODO: The CTL registers can configure internal pullup/pulldown resistors.
124 this->write_byte(MPR121_GPIOCTL0, 0x00);
125 this->write_byte(MPR121_GPIOCTL1, 0x00);
128
129 if (!this->write_byte(MPR121_GPIODATA, this->gpio_output_)) {
130 this->status_set_warning();
131 return false;
132 }
133
134 this->status_clear_warning();
135 return true;
136}
137
138void MPR121GPIOPin::setup() { this->pin_mode(this->flags_); }
139
141 assert(this->pin_ >= 4);
142 this->parent_->pin_mode(this->pin_ - 4, flags);
143}
144
146 assert(this->pin_ >= 4);
147 return this->parent_->digital_read(this->pin_ - 4) != this->inverted_;
148}
149
151 assert(this->pin_ >= 4);
152 this->parent_->digital_write(this->pin_ - 4, value != this->inverted_);
153}
154
155size_t MPR121GPIOPin::dump_summary(char *buffer, size_t len) const {
156 return buf_append_printf(buffer, len, 0, "ELE%u on MPR121", this->pin_);
157}
158
159} // namespace esphome::mpr121
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:272
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.h:493
void enable_loop()
Enable this component's loop.
Definition component.h:246
void disable_loop()
Disable this component's loop.
void status_clear_warning()
Definition component.h:289
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:265
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:240
bool read_byte_16(uint8_t a_register, uint16_t *data)
Definition i2c.h:249
uint8_t gpio_enable_
The enable mask - zero means high Z, 1 means GPIO usage.
Definition mpr121.h:95
bool digital_read(uint8_t ionum)
Definition mpr121.cpp:97
void set_release_debounce(uint8_t debounce)
Definition mpr121.cpp:64
uint8_t gpio_direction_
Mask for the pin mode - 1 means output, 0 means input.
Definition mpr121.h:97
std::vector< MPR121Channel * > channels_
Definition mpr121.h:82
uint8_t gpio_output_
The mask to write as output state - 1 means HIGH, 0 means LOW.
Definition mpr121.h:99
enum esphome::mpr121::MPR121Component::ErrorCode NONE
void digital_write(uint8_t ionum, bool value)
Definition mpr121.cpp:99
void pin_mode(uint8_t ionum, gpio::Flags flags)
Definition mpr121.cpp:108
uint8_t gpio_input_
The mask to read as input state - 1 means HIGH, 0 means LOW.
Definition mpr121.h:101
void set_touch_debounce(uint8_t debounce)
Definition mpr121.cpp:58
void digital_write(bool value) override
Definition mpr121.cpp:150
void pin_mode(gpio::Flags flags) override
Definition mpr121.cpp:140
size_t dump_summary(char *buffer, size_t len) const override
Definition mpr121.cpp:155
MPR121Component * parent_
Definition mpr121.h:121
bool digital_read() override
Definition mpr121.cpp:145
uint16_t flags
mopeka_std_values val[3]
@ FLAG_OUTPUT
Definition gpio.h:28
@ FLAG_INPUT
Definition gpio.h:27
@ MPR121_TOUCHSTATUS_L
Definition mpr121.h:14
const void size_t len
Definition hal.h:64