6namespace rotary_encoder {
8static const char *
const TAG =
"rotary_encoder";
11static const uint8_t STATE_LUT_MASK = 0x1C;
12static const uint16_t STATE_PIN_A_HIGH = 0x01;
13static const uint16_t STATE_PIN_B_HIGH = 0x02;
14static const uint16_t STATE_S0 = 0x00;
15static const uint16_t STATE_S1 = 0x04;
16static const uint16_t STATE_S2 = 0x08;
17static const uint16_t STATE_S3 = 0x0C;
18static const uint16_t STATE_CCW = 0x00;
19static const uint16_t STATE_CW = 0x10;
20static const uint16_t STATE_HAS_INCREMENTED = 0x0700;
21static const uint16_t STATE_INCREMENT_COUNTER_4 = 0x0700;
22static const uint16_t STATE_INCREMENT_COUNTER_2 = 0x0300;
23static const uint16_t STATE_INCREMENT_COUNTER_1 = 0x0100;
24static const uint16_t STATE_HAS_DECREMENTED = 0x7000;
25static const uint16_t STATE_DECREMENT_COUNTER_4 = 0x7000;
26static const uint16_t STATE_DECREMENT_COUNTER_2 = 0x3000;
27static const uint16_t STATE_DECREMENT_COUNTER_1 = 0x1000;
41static const uint16_t DRAM_ATTR STATE_LOOKUP_TABLE[32] = {
44 STATE_CW | STATE_S1 | STATE_INCREMENT_COUNTER_1,
46 STATE_CCW | STATE_S3 | STATE_DECREMENT_COUNTER_4,
50 STATE_CCW | STATE_S0 | STATE_DECREMENT_COUNTER_1,
51 STATE_CW | STATE_S2 | STATE_INCREMENT_COUNTER_4,
53 STATE_CCW | STATE_S1 | STATE_DECREMENT_COUNTER_2,
55 STATE_CW | STATE_S3 | STATE_INCREMENT_COUNTER_1,
58 STATE_CW | STATE_S0 | STATE_INCREMENT_COUNTER_2,
59 STATE_CCW | STATE_S2 | STATE_DECREMENT_COUNTER_1,
65 STATE_CW | STATE_S1 | STATE_INCREMENT_COUNTER_1,
67 STATE_CCW | STATE_S3 | STATE_DECREMENT_COUNTER_4,
71 STATE_CCW | STATE_S0 | STATE_DECREMENT_COUNTER_1,
72 STATE_CW | STATE_S2 | STATE_INCREMENT_COUNTER_4,
74 STATE_CCW | STATE_S1 | STATE_DECREMENT_COUNTER_2,
76 STATE_CW | STATE_S3 | STATE_INCREMENT_COUNTER_1,
79 STATE_CW | STATE_S0 | STATE_INCREMENT_COUNTER_2,
80 STATE_CCW | STATE_S2 | STATE_DECREMENT_COUNTER_1,
87 uint8_t input_state = arg->
state & STATE_LUT_MASK;
89 input_state |= STATE_PIN_A_HIGH;
91 input_state |= STATE_PIN_B_HIGH;
93 int8_t rotation_dir = 0;
94 uint16_t new_state = STATE_LOOKUP_TABLE[input_state];
95 if ((new_state & arg->
resolution & STATE_HAS_INCREMENTED) != 0) {
102 if ((new_state & arg->
resolution & STATE_HAS_DECREMENTED) != 0) {
113 || std::signbit(*std::prev(first_zero)) !=
114 std::signbit(rotation_dir)
115 || *std::prev(first_zero) == std::numeric_limits<int8_t>::lowest()
116 || *std::prev(first_zero) == std::numeric_limits<int8_t>::max()) {
118 *first_zero += rotation_dir;
123 *std::prev(first_zero) += rotation_dir;
128 arg->
state = new_state;
132 ESP_LOGCONFIG(TAG,
"Setting up Rotary Encoder '%s'...", this->
name_.
c_str());
134 int32_t initial_value = 0;
138 if (!this->
rtc_.
load(&initial_value)) {
156 if (this->
pin_i_ !=
nullptr) {
164 LOG_SENSOR(
"",
"Rotary Encoder",
this);
165 LOG_PIN(
" Pin A: ", this->
pin_a_);
166 LOG_PIN(
" Pin B: ", this->
pin_b_);
167 LOG_PIN(
" Pin I: ", this->
pin_i_);
169 const LogString *restore_mode;
172 restore_mode = LOG_STR(
"Restore (Defaults to zero)");
175 restore_mode = LOG_STR(
"Always zero");
178 restore_mode = LOG_STR(
"");
180 ESP_LOGCONFIG(TAG,
" Restore Mode: %s", LOG_STR_ARG(restore_mode));
184 ESP_LOGCONFIG(TAG,
" Resolution: 1 Pulse Per Cycle");
187 ESP_LOGCONFIG(TAG,
" Resolution: 2 Pulses Per Cycle");
190 ESP_LOGCONFIG(TAG,
" Resolution: 4 Pulse Per Cycle");
195 std::array<int8_t, 8> rotation_events;
196 bool rotation_events_overflow;
206 if (rotation_events_overflow) {
207 ESP_LOGW(TAG,
"Captured more rotation events than expected");
210 for (
auto events : rotation_events) {
229 if (this->
store_.
last_read != counter || this->publish_initial_value_) {