^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ============================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) rotary-encoder - a generic driver for GPIO connected devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ============================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) :Author: Daniel Mack <daniel@caiaq.de>, Feb 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) Function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) --------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) Rotary encoders are devices which are connected to the CPU or other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) peripherals with two wires. The outputs are phase-shifted by 90 degrees
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) and by triggering on falling and rising edges, the turn direction can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) be determined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) Some encoders have both outputs low in stable states, others also have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) a stable state with both outputs high (half-period mode) and some have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) a stable state in all steps (quarter-period mode).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) The phase diagram of these two outputs look like this::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) _____ _____ _____
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) | | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) Channel A ____| |_____| |_____| |____
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) : : : : : : : : : : : :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) __ _____ _____ _____
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) | | | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) Channel B |_____| |_____| |_____| |__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) : : : : : : : : : : : :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) Event a b c d a b c d a b c d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) |<-------->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) one step
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) |<-->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) one step (half-period mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) |<>|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) one step (quarter-period mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) For more information, please see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) https://en.wikipedia.org/wiki/Rotary_encoder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) Events / state machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ----------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) In half-period mode, state a) and c) above are used to determine the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) rotational direction based on the last stable state. Events are reported in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) states b) and d) given that the new stable state is different from the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) (i.e. the rotation was not reversed half-way).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) Otherwise, the following apply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) a) Rising edge on channel A, channel B in low state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) This state is used to recognize a clockwise turn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) b) Rising edge on channel B, channel A in high state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) When entering this state, the encoder is put into 'armed' state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) meaning that there it has seen half the way of a one-step transition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) c) Falling edge on channel A, channel B in high state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) This state is used to recognize a counter-clockwise turn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) d) Falling edge on channel B, channel A in low state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) Parking position. If the encoder enters this state, a full transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) should have happened, unless it flipped back on half the way. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 'armed' state tells us about that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) Platform requirements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ---------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) As there is no hardware dependent call in this driver, the platform it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) used with must support gpiolib. Another requirement is that IRQs must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) able to fire on both edges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) Board integration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) -----------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) To use this driver in your system, register a platform_device with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) name 'rotary-encoder' and associate the IRQs and some specific platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) data with it. Because the driver uses generic device properties, this can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) be done either via device tree, ACPI, or using static board files, like in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) example below:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* board support file example */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #include <linux/gpio/machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define GPIO_ROTARY_A 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define GPIO_ROTARY_B 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static struct gpiod_lookup_table rotary_encoder_gpios = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .dev_id = "rotary-encoder.0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) GPIO_LOOKUP_IDX("gpio-0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) GPIO_ROTARY_A, NULL, 0, GPIO_ACTIVE_LOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) GPIO_LOOKUP_IDX("gpio-0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) GPIO_ROTARY_B, NULL, 1, GPIO_ACTIVE_HIGH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const struct property_entry rotary_encoder_properties[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) PROPERTY_ENTRY_U32("rotary-encoder,steps-per-period", 24),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) PROPERTY_ENTRY_U32("linux,axis", ABS_X),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) PROPERTY_ENTRY_U32("rotary-encoder,relative_axis", 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct platform_device rotary_encoder_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .name = "rotary-encoder",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) gpiod_add_lookup_table(&rotary_encoder_gpios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) device_add_properties(&rotary_encoder_device, rotary_encoder_properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) platform_device_register(&rotary_encoder_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) Please consult device tree binding documentation to see all properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) supported by the driver.