7static const char *
const TAG =
"rotary_encoder";
10static const uint8_t STATE_LUT_MASK = 0x1C;
11static const uint16_t STATE_PIN_A_HIGH = 0x01;
12static const uint16_t STATE_PIN_B_HIGH = 0x02;
13static const uint16_t STATE_S0 = 0x00;
14static const uint16_t STATE_S1 = 0x04;
15static const uint16_t STATE_S2 = 0x08;
16static const uint16_t STATE_S3 = 0x0C;
17static const uint16_t STATE_CCW = 0x00;
18static const uint16_t STATE_CW = 0x10;
19static const uint16_t STATE_HAS_INCREMENTED = 0x0700;
20static const uint16_t STATE_INCREMENT_COUNTER_4 = 0x0700;
21static const uint16_t STATE_INCREMENT_COUNTER_2 = 0x0300;
22static const uint16_t STATE_INCREMENT_COUNTER_1 = 0x0100;
23static const uint16_t STATE_HAS_DECREMENTED = 0x7000;
24static const uint16_t STATE_DECREMENT_COUNTER_4 = 0x7000;
25static const uint16_t STATE_DECREMENT_COUNTER_2 = 0x3000;
26static const uint16_t STATE_DECREMENT_COUNTER_1 = 0x1000;
40static const uint16_t DRAM_ATTR STATE_LOOKUP_TABLE[32] = {
43 STATE_CW | STATE_S1 | STATE_INCREMENT_COUNTER_1,
45 STATE_CCW | STATE_S3 | STATE_DECREMENT_COUNTER_4,
49 STATE_CCW | STATE_S0 | STATE_DECREMENT_COUNTER_1,
50 STATE_CW | STATE_S2 | STATE_INCREMENT_COUNTER_4,
52 STATE_CCW | STATE_S1 | STATE_DECREMENT_COUNTER_2,
54 STATE_CW | STATE_S3 | STATE_INCREMENT_COUNTER_1,
57 STATE_CW | STATE_S0 | STATE_INCREMENT_COUNTER_2,
58 STATE_CCW | STATE_S2 | STATE_DECREMENT_COUNTER_1,
64 STATE_CW | STATE_S1 | STATE_INCREMENT_COUNTER_1,
66 STATE_CCW | STATE_S3 | STATE_DECREMENT_COUNTER_4,
70 STATE_CCW | STATE_S0 | STATE_DECREMENT_COUNTER_1,
71 STATE_CW | STATE_S2 | STATE_INCREMENT_COUNTER_4,
73 STATE_CCW | STATE_S1 | STATE_DECREMENT_COUNTER_2,
75 STATE_CW | STATE_S3 | STATE_INCREMENT_COUNTER_1,
78 STATE_CW | STATE_S0 | STATE_INCREMENT_COUNTER_2,
79 STATE_CCW | STATE_S2 | STATE_DECREMENT_COUNTER_1,
86 uint8_t input_state = arg->
state & STATE_LUT_MASK;
88 input_state |= STATE_PIN_A_HIGH;
90 input_state |= STATE_PIN_B_HIGH;
92 int8_t rotation_dir = 0;
93 uint16_t new_state = STATE_LOOKUP_TABLE[input_state];
94 if ((new_state & arg->
resolution & STATE_HAS_INCREMENTED) != 0) {
101 if ((new_state & arg->
resolution & STATE_HAS_DECREMENTED) != 0) {
112 || std::signbit(*std::prev(first_zero)) !=
113 std::signbit(rotation_dir)
114 || *std::prev(first_zero) == std::numeric_limits<int8_t>::lowest()
115 || *std::prev(first_zero) == std::numeric_limits<int8_t>::max()) {
117 *first_zero += rotation_dir;
122 *std::prev(first_zero) += rotation_dir;
127 arg->
state = new_state;
131 int32_t initial_value = 0;
135 if (!this->
rtc_.
load(&initial_value)) {
143 initial_value = clamp(initial_value, this->
store_.
min_value, this->store_.max_value);
153 if (this->
pin_i_ !=
nullptr) {
161 LOG_SENSOR(
"",
"Rotary Encoder",
this);
162 LOG_PIN(
" Pin A: ", this->
pin_a_);
163 LOG_PIN(
" Pin B: ", this->
pin_b_);
164 LOG_PIN(
" Pin I: ", this->
pin_i_);
166 const LogString *restore_mode;
169 restore_mode = LOG_STR(
"Restore (Defaults to zero)");
172 restore_mode = LOG_STR(
"Always zero");
175 restore_mode = LOG_STR(
"");
177 ESP_LOGCONFIG(TAG,
" Restore Mode: %s", LOG_STR_ARG(restore_mode));
181 ESP_LOGCONFIG(TAG,
" Resolution: 1 Pulse Per Cycle");
184 ESP_LOGCONFIG(TAG,
" Resolution: 2 Pulses Per Cycle");
187 ESP_LOGCONFIG(TAG,
" Resolution: 4 Pulse Per Cycle");
192 std::array<int8_t, 8> rotation_events;
193 bool rotation_events_overflow;
203 if (rotation_events_overflow) {
204 ESP_LOGW(TAG,
"Captured more rotation events than expected");
207 for (
auto events : rotation_events) {
226 if (this->
store_.
last_read != counter || this->publish_initial_value_) {