-
Notifications
You must be signed in to change notification settings - Fork 12
/
Romi32U4Encoders.cpp
149 lines (119 loc) · 3.44 KB
/
Romi32U4Encoders.cpp
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
// Copyright Pololu Corporation. For more information, see http://www.pololu.com/
#include <Romi32U4Encoders.h>
#include <FastGPIO.h>
#include <avr/interrupt.h>
#include <Arduino.h>
#define LEFT_XOR 8
#define LEFT_B IO_E2
#define RIGHT_XOR 7
#define RIGHT_B 23
static volatile bool lastLeftA;
static volatile bool lastLeftB;
static volatile bool lastRightA;
static volatile bool lastRightB;
static volatile bool errorLeft;
static volatile bool errorRight;
// These count variables are uint16_t instead of int16_t because
// signed integer overflow is undefined behavior in C++.
static volatile uint16_t countLeft;
static volatile uint16_t countRight;
ISR(PCINT0_vect)
{
bool newLeftB = FastGPIO::Pin<LEFT_B>::isInputHigh();
bool newLeftA = FastGPIO::Pin<LEFT_XOR>::isInputHigh() ^ newLeftB;
countLeft += (lastLeftA ^ newLeftB) - (newLeftA ^ lastLeftB);
if((lastLeftA ^ newLeftA) & (lastLeftB ^ newLeftB))
{
errorLeft = true;
}
lastLeftA = newLeftA;
lastLeftB = newLeftB;
}
static void rightISR()
{
bool newRightB = FastGPIO::Pin<RIGHT_B>::isInputHigh();
bool newRightA = FastGPIO::Pin<RIGHT_XOR>::isInputHigh() ^ newRightB;
countRight += (lastRightA ^ newRightB) - (newRightA ^ lastRightB);
if((lastRightA ^ newRightA) & (lastRightB ^ newRightB))
{
errorRight = true;
}
lastRightA = newRightA;
lastRightB = newRightB;
}
void Romi32U4Encoders::init2()
{
// Set the pins as pulled-up inputs.
FastGPIO::Pin<LEFT_XOR>::setInputPulledUp();
FastGPIO::Pin<LEFT_B>::setInputPulledUp();
FastGPIO::Pin<RIGHT_XOR>::setInputPulledUp();
FastGPIO::Pin<RIGHT_B>::setInputPulledUp();
// Enable pin-change interrupt on PB4 for left encoder, and disable other
// pin-change interrupts.
PCICR = (1 << PCIE0);
PCMSK0 = (1 << PCINT4);
PCIFR = (1 << PCIF0); // Clear its interrupt flag by writing a 1.
// Enable interrupt on PE6 for the right encoder. We use attachInterrupt
// instead of defining ISR(INT6_vect) ourselves so that this class will be
// compatible with other code that uses attachInterrupt.
attachInterrupt(4, rightISR, CHANGE);
// Initialize the variables. It's good to do this after enabling the
// interrupts in case the interrupts fired by accident as we were enabling
// them.
lastLeftB = FastGPIO::Pin<LEFT_B>::isInputHigh();
lastLeftA = FastGPIO::Pin<LEFT_XOR>::isInputHigh() ^ lastLeftB;
countLeft = 0;
errorLeft = 0;
lastRightB = FastGPIO::Pin<RIGHT_B>::isInputHigh();
lastRightA = FastGPIO::Pin<RIGHT_XOR>::isInputHigh() ^ lastRightB;
countRight = 0;
errorRight = 0;
}
int16_t Romi32U4Encoders::getCountsLeft()
{
init();
cli();
int16_t counts = countLeft;
sei();
return counts;
}
int16_t Romi32U4Encoders::getCountsRight()
{
init();
cli();
int16_t counts = countRight;
sei();
return counts;
}
int16_t Romi32U4Encoders::getCountsAndResetLeft()
{
init();
cli();
int16_t counts = countLeft;
countLeft = 0;
sei();
return counts;
}
int16_t Romi32U4Encoders::getCountsAndResetRight()
{
init();
cli();
int16_t counts = countRight;
countRight = 0;
sei();
return counts;
}
bool Romi32U4Encoders::checkErrorLeft()
{
init();
bool error = errorLeft;
errorLeft = 0;
return error;
}
bool Romi32U4Encoders::checkErrorRight()
{
init();
bool error = errorRight;
errorRight = 0;
return error;
}