forked from pavius/rotary-encoder-timer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquadenc.c
187 lines (163 loc) · 5.77 KB
/
quadenc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/**************************************************************************
*
* FILE NAME: quadenc.c
* FILE DESCRIPTION: QUADENC driver
* FILE CREATION DATE: 9-01-2010
*
*==========================================================================
* This document contains confidential information which is protected by copyright
* and is proprietary. No part of this document may be used, copied, disclosed,
* or conveyed to another party without prior written consent of its owner
***************************************************************************
*
* Modification history:
* --------------------
* 01a,9jan10 erd written
*
***************************************************************************/
#include "sysdef.h"
#include "sys.h"
#include "quadenc_prv.h"
// ==========================================================================
// init
void quadenc_init(void)
{
// init locals
quadenc_channel0SearchPattern = 0;
quadenc_channel1SearchPattern = 0;
quadenc_channel0Status = 0xFF;
quadenc_channel1Status = 0xFF;
quadenc_buttonStatus = 0xFF;
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
quadenc_changeCounts = 0;
}
// ==========================================================================
// get last number of counts
void quadenc_getLastChangeCount(int_8 *counts)
{
// disable interrupts
// sys_disableInterrupts();
// get how many counts changed since last poll
*counts += quadenc_changeCounts;
// zero it out
quadenc_changeCounts = 0;
// enable interrupts
// sys_enableInterrupts();
}
// ==========================================================================
// ISR
void quadenc_isr(void)
{
//
// Debounce channel 0
//
// shift channel0 value into status. Save only N bits history
quadenc_channel0Status = ((quadenc_channel0Status << 1) | RB0) & 0x7;
// do lower 3 bits match search pattern?
if (quadenc_channel0Status == quadenc_channel0SearchPattern)
{
// change search pattern
quadenc_channel0SearchPattern = ((~quadenc_channel0SearchPattern) & 0x7);
// declare debounced transition
quadenc_transitionEvent = quadenc_channel0Status;
}
//
// Debounce channel 1
//
// shift channel0 value into status. Save only N bits history
quadenc_channel1Status = ((quadenc_channel1Status << 1) | RB1) & 0x7;
// do lower 3 bits match search pattern?
if (quadenc_channel1Status == quadenc_channel1SearchPattern)
{
// change search pattern
quadenc_channel1SearchPattern = ((~quadenc_channel1SearchPattern) & 0x7);
// declare debounced transition
quadenc_transitionEvent = (quadenc_channel1Status | (1 << 3));
}
//
// Check if transition forms an acceptable movement
//
// check if a transition occured
if (quadenc_transitionEvent != QUADENC_NO_TRANSITION_EVENT)
{
//
// Idle state
//
if (quadenc_state == QUADENC_STATE_IDLE)
{
// first value of CW transition?
if (quadenc_transitionEvent == quadenc_cwTransitions[0])
{
// yup - enter state
quadenc_state = QUADENC_STATE_DETECTING_CW;
// next transition
quadenc_transitionEventIndex++;
}
// first value of CCW transition?
else if (quadenc_transitionEvent == quadenc_ccwTransitions[0])
{
// yup - enter state
quadenc_state = QUADENC_STATE_DETECTING_CCW;
// next transition
quadenc_transitionEventIndex++;
}
}
//
// CW state
//
else if (quadenc_state == QUADENC_STATE_DETECTING_CW)
{
// found next expected transition?
if (quadenc_transitionEvent == quadenc_cwTransitions[quadenc_transitionEventIndex])
{
// increment it
quadenc_transitionEventIndex++;
// are we done?
if (quadenc_transitionEventIndex == 4)
{
// decrement count
quadenc_changeCounts++;
// back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}
else
{
// incorrect transition, back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}
//
// CCW state
//
else if (quadenc_state == QUADENC_STATE_DETECTING_CCW)
{
// found next expected transition?
if (quadenc_transitionEvent == quadenc_ccwTransitions[quadenc_transitionEventIndex])
{
// increment it
quadenc_transitionEventIndex++;
// are we done?
if (quadenc_transitionEventIndex == 4)
{
// increment count
quadenc_changeCounts--;
// back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}
else
{
// incorrect transition, back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}
// zero out transition
quadenc_transitionEvent = QUADENC_NO_TRANSITION_EVENT;
}
}