Back to home page

OSCL-LXR

 
 

    


0001 ============================================================
0002 rotary-encoder - a generic driver for GPIO connected devices
0003 ============================================================
0004 
0005 :Author: Daniel Mack <daniel@caiaq.de>, Feb 2009
0006 
0007 Function
0008 --------
0009 
0010 Rotary encoders are devices which are connected to the CPU or other
0011 peripherals with two wires. The outputs are phase-shifted by 90 degrees
0012 and by triggering on falling and rising edges, the turn direction can
0013 be determined.
0014 
0015 Some encoders have both outputs low in stable states, others also have
0016 a stable state with both outputs high (half-period mode) and some have
0017 a stable state in all steps (quarter-period mode).
0018 
0019 The phase diagram of these two outputs look like this::
0020 
0021                   _____       _____       _____
0022                  |     |     |     |     |     |
0023   Channel A  ____|     |_____|     |_____|     |____
0024 
0025                  :  :  :  :  :  :  :  :  :  :  :  :
0026             __       _____       _____       _____
0027               |     |     |     |     |     |     |
0028   Channel B   |_____|     |_____|     |_____|     |__
0029 
0030                  :  :  :  :  :  :  :  :  :  :  :  :
0031   Event          a  b  c  d  a  b  c  d  a  b  c  d
0032 
0033                 |<-------->|
0034                   one step
0035 
0036                 |<-->|
0037                   one step (half-period mode)
0038 
0039                 |<>|
0040                   one step (quarter-period mode)
0041 
0042 For more information, please see
0043         https://en.wikipedia.org/wiki/Rotary_encoder
0044 
0045 
0046 Events / state machine
0047 ----------------------
0048 
0049 In half-period mode, state a) and c) above are used to determine the
0050 rotational direction based on the last stable state. Events are reported in
0051 states b) and d) given that the new stable state is different from the last
0052 (i.e. the rotation was not reversed half-way).
0053 
0054 Otherwise, the following apply:
0055 
0056 a) Rising edge on channel A, channel B in low state
0057         This state is used to recognize a clockwise turn
0058 
0059 b) Rising edge on channel B, channel A in high state
0060         When entering this state, the encoder is put into 'armed' state,
0061         meaning that there it has seen half the way of a one-step transition.
0062 
0063 c) Falling edge on channel A, channel B in high state
0064         This state is used to recognize a counter-clockwise turn
0065 
0066 d) Falling edge on channel B, channel A in low state
0067         Parking position. If the encoder enters this state, a full transition
0068         should have happened, unless it flipped back on half the way. The
0069         'armed' state tells us about that.
0070 
0071 Platform requirements
0072 ---------------------
0073 
0074 As there is no hardware dependent call in this driver, the platform it is
0075 used with must support gpiolib. Another requirement is that IRQs must be
0076 able to fire on both edges.
0077 
0078 
0079 Board integration
0080 -----------------
0081 
0082 To use this driver in your system, register a platform_device with the
0083 name 'rotary-encoder' and associate the IRQs and some specific platform
0084 data with it. Because the driver uses generic device properties, this can
0085 be done either via device tree, ACPI, or using static board files, like in
0086 example below:
0087 
0088 ::
0089 
0090         /* board support file example */
0091 
0092         #include <linux/input.h>
0093         #include <linux/gpio/machine.h>
0094         #include <linux/property.h>
0095 
0096         #define GPIO_ROTARY_A 1
0097         #define GPIO_ROTARY_B 2
0098 
0099         static struct gpiod_lookup_table rotary_encoder_gpios = {
0100                 .dev_id = "rotary-encoder.0",
0101                 .table = {
0102                         GPIO_LOOKUP_IDX("gpio-0",
0103                                         GPIO_ROTARY_A, NULL, 0, GPIO_ACTIVE_LOW),
0104                         GPIO_LOOKUP_IDX("gpio-0",
0105                                         GPIO_ROTARY_B, NULL, 1, GPIO_ACTIVE_HIGH),
0106                         { },
0107                 },
0108         };
0109 
0110         static const struct property_entry rotary_encoder_properties[] = {
0111                 PROPERTY_ENTRY_U32("rotary-encoder,steps-per-period", 24),
0112                 PROPERTY_ENTRY_U32("linux,axis",                      ABS_X),
0113                 PROPERTY_ENTRY_U32("rotary-encoder,relative_axis",    0),
0114                 { },
0115         };
0116 
0117         static const struct software_node rotary_encoder_node = {
0118                 .properties = rotary_encoder_properties,
0119         };
0120 
0121         static struct platform_device rotary_encoder_device = {
0122                 .name           = "rotary-encoder",
0123                 .id             = 0,
0124         };
0125 
0126         ...
0127 
0128         gpiod_add_lookup_table(&rotary_encoder_gpios);
0129         device_add_software_node(&rotary_encoder_device.dev, &rotary_encoder_node);
0130         platform_device_register(&rotary_encoder_device);
0131 
0132         ...
0133 
0134 Please consult device tree binding documentation to see all properties
0135 supported by the driver.