-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencoder.c
82 lines (78 loc) · 3.03 KB
/
encoder.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
//------------------------------------------ class ENCODER ------------------------------------------------------
class ENCODER {
public:
ENCODER(byte aPIN, byte bPIN, int16_t initPos = 0) {
pt = 0; mPIN = aPIN; sPIN = bPIN; pos = initPos;
min_pos = -32767; max_pos = 32766; channelB = false; increment = 1;
changed = 0;
is_looped = false;
}
void init(void) {
pinMode(mPIN, INPUT_PULLUP);
pinMode(sPIN, INPUT_PULLUP);
}
void set_increment(byte inc) { increment = inc; }
byte get_increment(void) { return increment; }
int16_t read(void) { return pos; }
void reset(int16_t initPos, int16_t low, int16_t upp, byte inc = 1, byte fast_inc = 0, bool looped = false);
bool write(int16_t initPos);
void cnangeINTR(void);
private:
int32_t min_pos, max_pos;
volatile uint32_t pt; // Time in ms when the encoder was rotaded
volatile uint32_t changed; // Time in ms when the value was changed
volatile bool channelB;
volatile int16_t pos; // Encoder current position
byte mPIN, sPIN; // The pin numbers connected to the main channel and to the socondary channel
bool is_looped; // Whether the encoder is looped
byte increment; // The value to add or substract for each encoder tick
byte fast_increment; // The value to change encoder when in runs quickly
const uint16_t fast_timeout = 300; // Time in ms to change encodeq quickly
const uint16_t overPress = 1000;
};
bool ENCODER::write(int16_t initPos) {
if ((initPos >= min_pos) && (initPos <= max_pos)) {
pos = initPos;
return true;
}
return false;
}
void ENCODER::reset(int16_t initPos, int16_t low, int16_t upp, byte inc, byte fast_inc, bool looped) {
min_pos = low; max_pos = upp;
if (!write(initPos)) initPos = min_pos;
increment = fast_increment = inc;
if (fast_inc > increment) fast_increment = fast_inc;
is_looped = looped;
}
void ENCODER::cnangeINTR(void) { // Interrupt function, called when the channel A of encoder changed
bool rUp = digitalRead(mPIN);
unsigned long now_t = millis();
if (!rUp) { // The channel A has been "pressed"
if ((pt == 0) || (now_t - pt > overPress)) {
pt = now_t;
channelB = digitalRead(sPIN);
}
} else {
if (pt > 0) {
byte inc = increment;
if ((now_t - pt) < overPress) {
if ((now_t - changed) < fast_timeout) inc = fast_increment;
changed = now_t;
if (channelB) pos -= inc; else pos += inc;
if (pos > max_pos) {
if (is_looped)
pos = min_pos;
else
pos = max_pos;
}
if (pos < min_pos) {
if (is_looped)
pos = max_pos;
else
pos = min_pos;
}
}
pt = 0;
}
}
}