Input: rotary-encoder - add support for half-period encoders
Add support for encoders that have two detents per input signal period. Signed-off-by: Johan Hovold <jhovold@gmail.com> Acked-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
parent
521a8f5cb7
commit
e70bdd41bd
|
@ -9,6 +9,9 @@ peripherals with two wires. The outputs are phase-shifted by 90 degrees
|
|||
and by triggering on falling and rising edges, the turn direction can
|
||||
be determined.
|
||||
|
||||
Some encoders have both outputs low in stable states, whereas others also have
|
||||
a stable state with both outputs high (half-period mode).
|
||||
|
||||
The phase diagram of these two outputs look like this:
|
||||
|
||||
_____ _____ _____
|
||||
|
@ -26,6 +29,8 @@ The phase diagram of these two outputs look like this:
|
|||
|<-------->|
|
||||
one step
|
||||
|
||||
|<-->|
|
||||
one step (half-period mode)
|
||||
|
||||
For more information, please see
|
||||
http://en.wikipedia.org/wiki/Rotary_encoder
|
||||
|
@ -34,6 +39,13 @@ For more information, please see
|
|||
1. Events / state machine
|
||||
-------------------------
|
||||
|
||||
In half-period mode, state a) and c) above are used to determine the
|
||||
rotational direction based on the last stable state. Events are reported in
|
||||
states b) and d) given that the new stable state is different from the last
|
||||
(i.e. the rotation was not reversed half-way).
|
||||
|
||||
Otherwise, the following apply:
|
||||
|
||||
a) Rising edge on channel A, channel B in low state
|
||||
This state is used to recognize a clockwise turn
|
||||
|
||||
|
@ -96,6 +108,7 @@ static struct rotary_encoder_platform_data my_rotary_encoder_info = {
|
|||
.gpio_b = GPIO_ROTARY_B,
|
||||
.inverted_a = 0,
|
||||
.inverted_b = 0,
|
||||
.half_period = false,
|
||||
};
|
||||
|
||||
static struct platform_device rotary_encoder_device = {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* rotary_encoder.c
|
||||
*
|
||||
* (c) 2009 Daniel Mack <daniel@caiaq.de>
|
||||
* Copyright (C) 2011 Johan Hovold <jhovold@gmail.com>
|
||||
*
|
||||
* state machine code inspired by code from Tim Ruetz
|
||||
*
|
||||
|
@ -38,6 +39,8 @@ struct rotary_encoder {
|
|||
|
||||
bool armed;
|
||||
unsigned char dir; /* 0 - clockwise, 1 - CCW */
|
||||
|
||||
char last_stable;
|
||||
};
|
||||
|
||||
static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata)
|
||||
|
@ -112,11 +115,37 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct rotary_encoder *encoder = dev_id;
|
||||
int state;
|
||||
|
||||
state = rotary_encoder_get_state(encoder->pdata);
|
||||
|
||||
switch (state) {
|
||||
case 0x00:
|
||||
case 0x03:
|
||||
if (state != encoder->last_stable) {
|
||||
rotary_encoder_report_event(encoder);
|
||||
encoder->last_stable = state;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
encoder->dir = (encoder->last_stable + state) & 0x01;
|
||||
break;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct rotary_encoder *encoder;
|
||||
struct input_dev *input;
|
||||
irq_handler_t handler;
|
||||
int err;
|
||||
|
||||
if (!pdata) {
|
||||
|
@ -187,7 +216,14 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* request the IRQs */
|
||||
err = request_irq(encoder->irq_a, &rotary_encoder_irq,
|
||||
if (pdata->half_period) {
|
||||
handler = &rotary_encoder_half_period_irq;
|
||||
encoder->last_stable = rotary_encoder_get_state(pdata);
|
||||
} else {
|
||||
handler = &rotary_encoder_irq;
|
||||
}
|
||||
|
||||
err = request_irq(encoder->irq_a, handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||
DRV_NAME, encoder);
|
||||
if (err) {
|
||||
|
@ -196,7 +232,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
|||
goto exit_free_gpio_b;
|
||||
}
|
||||
|
||||
err = request_irq(encoder->irq_b, &rotary_encoder_irq,
|
||||
err = request_irq(encoder->irq_b, handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||
DRV_NAME, encoder);
|
||||
if (err) {
|
||||
|
@ -264,5 +300,5 @@ module_exit(rotary_encoder_exit);
|
|||
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
MODULE_DESCRIPTION("GPIO rotary encoder driver");
|
||||
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
|
||||
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>, Johan Hovold");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -10,6 +10,7 @@ struct rotary_encoder_platform_data {
|
|||
unsigned int inverted_b;
|
||||
bool relative_axis;
|
||||
bool rollover;
|
||||
bool half_period;
|
||||
};
|
||||
|
||||
#endif /* __ROTARY_ENCODER_H__ */
|
||||
|
|
Loading…
Reference in New Issue