Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 250507
b: refs/heads/master
c: e70bdd4
h: refs/heads/master
i:
  250505: 254266c
  250503: 431fcbf
v: v3
  • Loading branch information
Johan Hovold authored and Dmitry Torokhov committed May 12, 2011
1 parent 461cde3 commit 7d840b6
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 521a8f5cb79d1017d00d26143227159674e3b79d
refs/heads/master: e70bdd41bd0ead91b4a43e9d656ac1569d7c8779
13 changes: 13 additions & 0 deletions trunk/Documentation/input/rotary-encoder.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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:

_____ _____ _____
Expand All @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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 = {
Expand Down
42 changes: 39 additions & 3 deletions trunk/drivers/input/misc/rotary_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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");
1 change: 1 addition & 0 deletions trunk/include/linux/rotary_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */

0 comments on commit 7d840b6

Please sign in to comment.