← Documents Documentation/input/devices/rotary-encoder.rst GitHub 원문 ↗

Linux 6.18.37 · Input

Rotary-encoder - A Generic Driver for GPIO Connected Devices

두 GPIO의 90도 위상차로 방향을 판별하는 회전식 엔코더 상태 머신과 보드 등록 방법을 설명합니다.

Source pathDocumentation/input/devices/rotary-encoder.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

rotary-encoder.rst:1-135

범용 회전식 엔코더 드라이버는 90도 위상차가 나는 두 GPIO의 에지 순서로 방향과 완전한 스텝을 판단합니다. full·half·quarter-period 모드의 안정점이 다르며, `armed` 상태로 중간 반전을 걸러냅니다.

문서 개요
항목내용
SourceDocumentation/input/devices/rotary-encoder.rst
분량135 source lines
입력90도 위상차 Channel A·B
모드full-, half-, quarter-period
상태a·b·c·d와 `armed`
플랫폼`gpiolib`, 양쪽 에지 IRQ
통합Device Tree, ACPI 또는 정적 board file

상태 머신과 플랫폼 요구사항을 요약합니다.

엔코더 이벤트 생성
두 GPIO와 active polarity 구성상승·하강 에지 IRQ 수신a~d 상태와 방향 후보 갱신설정 모드의 스텝 경계 확인완전한 전이에만 축 이벤트 보고

GPIO 전이에서 input 이벤트까지의 공통 흐름입니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

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

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

2채널 90도 위상과 스텝 모드

1-45

`rotary-encoder`는 GPIO에 연결된 회전식 엔코더용 범용 드라이버입니다. 엔코더의 두 출력은 90도 위상차를 가지며, 각 채널의 상승·하강 에지 순서를 관찰해 회전 방향을 판단합니다.

엔코더에 따라 안정 상태의 수가 다릅니다. 기본형은 두 출력이 모두 낮은 상태를 안정점으로 쓰고, half-period 모드는 둘 다 낮거나 둘 다 높은 상태를 안정점으로 사용합니다. quarter-period 모드는 네 상태 모두를 각 스텝의 안정점으로 취급합니다.

회전식 엔코더 위상 상태
상태Channel AChannel B진입 에지
aHighLowA rising
bHighHighB rising
cLowHighA falling
dLowLowB falling

원문의 Channel A/B 파형에서 a~d 한 주기를 논리 상태로 다시 그렸습니다.

모드별 한 스텝
모드한 스텝에 해당하는 전이안정 상태
full-perioda -> b -> c -> d -> 다음 a주기당 한 번
half-perioda -> b -> c 또는 c -> d -> aa와 c
quarter-perioda, b, c, d의 각 전이모든 상태

파형에서 한 기계적 스텝으로 묶는 상태 간격입니다.

위상으로 방향 판별
Channel A와 B의 현재 논리값 읽기두 채널의 상승·하강 에지 IRQ 수신a -> b -> c -> d 순서인지 역순인지 확인설정된 full·half·quarter-period 경계까지 전이완전한 스텝이면 시계 또는 반시계 이벤트 보고

두 GPIO의 에지 순서가 회전 이벤트가 되는 흐름입니다.

추가 원리는 원문에 연결된 Wikipedia `Rotary encoder` 문서를 참조할 수 있습니다. 드라이버 동작에서는 파형 자체보다 에지가 발생한 채널과 반대 채널의 현재 상태 조합이 중요합니다.

============================================================
rotary-encoder - a generic driver for GPIO connected devices
============================================================

:Author: Daniel Mack <daniel@caiaq.de>, Feb 2009

Function
--------

Rotary encoders are devices which are connected to the CPU or other
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, others also have
a stable state with both outputs high (half-period mode) and some have
a stable state in all steps (quarter-period mode).

The phase diagram of these two outputs look like this::

                  _____       _____       _____
                 |     |     |     |     |     |
  Channel A  ____|     |_____|     |_____|     |____

                 :  :  :  :  :  :  :  :  :  :  :  :
            __       _____       _____       _____
              |     |     |     |     |     |     |
  Channel B   |_____|     |_____|     |_____|     |__

                 :  :  :  :  :  :  :  :  :  :  :  :
  Event          a  b  c  d  a  b  c  d  a  b  c  d

                |<-------->|
                  one step

                |<-->|
                  one step (half-period mode)

                |<>|
                  one step (quarter-period mode)

For more information, please see
        https://en.wikipedia.org/wiki/Rotary_encoder

방향 판별과 armed 상태 머신

46-70

Half-period 모드에서는 위상도의 a와 c를 안정 상태로 사용해 마지막 안정 상태와 새 안정 상태를 비교합니다. 새 안정 상태가 이전과 다를 때 b 또는 d에서 이벤트를 보고하며, 중간에서 방향을 되돌린 경우에는 스텝으로 계산하지 않습니다.

기본 상태 머신 a~d
상태조건의미
aChannel A rising, B low시계 방향 회전 인식
bChannel B rising, A high`armed` 설정: 한 스텝의 절반을 통과
cChannel A falling, B high반시계 방향 회전 인식
dChannel B falling, A lowparking 위치에서 완전한 전이 확인

각 에지, 반대 채널 상태와 드라이버의 의미입니다.

b에서 설정되는 `armed`는 한 스텝 전이의 절반을 지났음을 기록합니다. d에 도착하면 보통 전체 전이가 끝났지만 중간에 되돌아왔을 수도 있으므로, `armed` 상태가 유효한 완전한 전이인지 구분합니다.

완전한 스텝 확인
a 또는 c에서 후보 방향 인식b 진입 시 `armed` 설정다음 에지 순서가 계속 진행되는지 확인d parking 위치에 도착`armed`가 유지됐으면 한 스텝 보고중간 반전이면 후보와 `armed`를 취소

중간 반전을 잘못된 회전 이벤트로 보고하지 않는 절차입니다.

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

b) Rising edge on channel B, channel A in high state
        When entering this state, the encoder is put into 'armed' state,
        meaning that there it has seen half the way of a one-step transition.

c) Falling edge on channel A, channel B in high state
        This state is used to recognize a counter-clockwise turn

d) Falling edge on channel B, channel A in low state
        Parking position. If the encoder enters this state, a full transition
        should have happened, unless it flipped back on half the way. The
        'armed' state tells us about that.

플랫폼 요구사항과 장치 등록 방식

71-87

드라이버에는 하드웨어 종속 호출이 없으므로 사용하는 플랫폼이 `gpiolib`을 지원해야 합니다. 또한 두 GPIO의 IRQ가 상승 에지와 하강 에지 모두에서 발생할 수 있어야 네 위상 상태를 빠짐없이 추적할 수 있습니다.

시스템에 통합하려면 이름이 `rotary-encoder`인 `platform_device`를 등록하고 IRQ와 장치별 속성을 연결합니다. 드라이버가 범용 device property를 사용하므로 Device Tree, ACPI, 정적 board file 중 어느 방식으로든 기술할 수 있습니다.

회전식 엔코더 플랫폼 조건
조건이유
`gpiolib` 지원두 채널을 범용 GPIO descriptor로 접근
양쪽 에지 IRQ상승·하강 네 전이를 모두 감지
`rotary-encoder` platform device드라이버와 장치 바인딩
device properties스텝 수, 축, 상대/절대 모드 설정

드라이버가 하드웨어 계층에 요구하는 기능입니다.

보드 통합 경로
두 엔코더 GPIO와 극성 정의양쪽 에지 IRQ가 가능한지 확인Device Tree·ACPI·board file 중 하나로 속성 기술`rotary-encoder` 장치 등록드라이버가 GPIO와 input 속성을 읽어 이벤트 장치 생성

플랫폼 펌웨어 방식과 무관한 공통 등록 구조입니다.

Platform requirements
---------------------

As there is no hardware dependent call in this driver, the platform it is
used with must support gpiolib. Another requirement is that IRQs must be
able to fire on both edges.


Board integration
-----------------

To use this driver in your system, register a platform_device with the
name 'rotary-encoder' and associate the IRQs and some specific platform
data with it. Because the driver uses generic device properties, this can
be done either via device tree, ACPI, or using static board files, like in
example below:

정적 보드 파일의 GPIO·속성 등록 예제

88-135

정적 board support file 예제는 `linux/input.h`, `linux/gpio/machine.h`, `linux/property.h`를 포함하고 GPIO 번호 1과 2를 `GPIO_ROTARY_A`, `GPIO_ROTARY_B`로 정의합니다.

예제 `gpiod_lookup_table`
항목Channel AChannel B
Device ID`rotary-encoder.0``rotary-encoder.0`
GPIO controller`gpio-0``gpio-0`
GPIO number`GPIO_ROTARY_A` = 1`GPIO_ROTARY_B` = 2
Consumer index01
Polarity`GPIO_ACTIVE_LOW``GPIO_ACTIVE_HIGH`

두 GPIO lookup 항목의 controller, index와 active polarity입니다.

예제 device properties
속성의미
`rotary-encoder,steps-per-period`24한 주기에 대응하는 스텝 설정
`linux,axis``ABS_X`보고할 Linux input 축
`rotary-encoder,relative_axis`0상대축이 아닌 절대축으로 설정

software node에 제공되는 세 속성입니다.

속성 배열은 `software_node`에 연결되고, platform device는 이름 `rotary-encoder`, ID 0으로 생성됩니다. 실제 등록 순서는 GPIO lookup table 추가, software node 연결, platform device 등록입니다.

정적 보드 파일 등록 순서
`gpiod_add_lookup_table(&rotary_encoder_gpios)``device_add_software_node(&rotary_encoder_device.dev, &rotary_encoder_node)``platform_device_register(&rotary_encoder_device)`드라이버 probe에서 GPIO·속성 조회`ABS_X` input 이벤트 장치 등록

예제의 세 API 호출이 구성 요소를 결합하는 흐름입니다.

드라이버가 지원하는 모든 속성은 Device Tree binding 문서를 참조해야 합니다. 예제 값은 정적 보드 파일에서 범용 property API를 사용하는 한 가지 구성일 뿐이며, 실제 엔코더의 분해능과 출력 극성에 맞춰야 합니다.

::

        /* board support file example */

        #include <linux/input.h>
        #include <linux/gpio/machine.h>
        #include <linux/property.h>

        #define GPIO_ROTARY_A 1
        #define GPIO_ROTARY_B 2

        static struct gpiod_lookup_table rotary_encoder_gpios = {
                .dev_id = "rotary-encoder.0",
                .table = {
                        GPIO_LOOKUP_IDX("gpio-0",
                                        GPIO_ROTARY_A, NULL, 0, GPIO_ACTIVE_LOW),
                        GPIO_LOOKUP_IDX("gpio-0",
                                        GPIO_ROTARY_B, NULL, 1, GPIO_ACTIVE_HIGH),
                        { },
                },
        };

        static const struct property_entry rotary_encoder_properties[] = {
                PROPERTY_ENTRY_U32("rotary-encoder,steps-per-period", 24),
                PROPERTY_ENTRY_U32("linux,axis",                      ABS_X),
                PROPERTY_ENTRY_U32("rotary-encoder,relative_axis",    0),
                { },
        };

        static const struct software_node rotary_encoder_node = {
                .properties = rotary_encoder_properties,
        };

        static struct platform_device rotary_encoder_device = {
                .name                = "rotary-encoder",
                .id                = 0,
        };

        ...

        gpiod_add_lookup_table(&rotary_encoder_gpios);
        device_add_software_node(&rotary_encoder_device.dev, &rotary_encoder_node);
        platform_device_register(&rotary_encoder_device);

        ...

Please consult device tree binding documentation to see all properties
supported by the driver.