-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPS2Events.cpp
239 lines (206 loc) · 5.58 KB
/
PS2Events.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
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
PS2Events.cpp - PS2Events library
Copyright (c) 2007 Free Software Foundation. All right reserved.
Written by Christian Weichel <[email protected]>
** Mostly rewritten Paul Stoffregen <[email protected]> 2010, 2011
** Modified for use beginning with Arduino 13 by L. Abraham Smith, <[email protected]> *
** Modified for easy interrup pin assignement on method begin(datapin,irq_pin). Cuningan <[email protected]> **
for more information you can read the original wiki in arduino.cc
at http://www.arduino.cc/playground/Main/PS2Events
or http://www.pjrc.com/teensy/td_libs_PS2Events.html
Version 2.3-Ctrl-Enter (September 2012)
- Add Ctrl+Enter (Ctrl+J) as PS2_LINEFEED, code 10
- Move PS2_DOWNARROW to code 12
Version 2.3-Ctrl (June 2012)
- Reintroduce Ctrl
Version 2.3 (October 2011)
- Minor bugs fixed
Version 2.2 (August 2011)
- Support non-US keyboards - thanks to Rainer Bruch for a German keyboard :)
Version 2.1 (May 2011)
- timeout to recover from misaligned input
- compatibility with Arduino "new-extension" branch
- TODO: send function, proposed by Scott Penrose, scooterda at me dot com
Version 2.0 (June 2010)
- Buffering added, many scan codes can be captured without data loss
if your sketch is busy doing other work
- Shift keys supported, completely rewritten scan code to ascii
- Slow linear search replaced with fast indexed table lookups
- Support for Teensy, Arduino Mega, and Sanguino added
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "PS2Events.h"
#define BUFFER_SIZE 45
static volatile uint8_t buffer[BUFFER_SIZE];
static volatile uint8_t head, tail;
static uint8_t DataPin;
static uint8_t CharBuffer=0;
static KeyEvent EventBuffer;
static uint8_t UTF8next=0;
// The ISR for the external interrupt
void ps2interrupt(void)
{
static uint8_t bitcount=0;
static uint8_t incoming=0;
static uint32_t prev_ms=0;
uint32_t now_ms;
uint8_t n, val;
val = digitalRead(DataPin);
now_ms = millis();
if (now_ms - prev_ms > 250) {
bitcount = 0;
incoming = 0;
}
prev_ms = now_ms;
n = bitcount - 1;
if (n <= 7) {
incoming |= (val << n);
}
bitcount++;
if (bitcount == 11) {
uint8_t i = head + 1;
if (i >= BUFFER_SIZE) i = 0;
if (i != tail) {
buffer[i] = incoming;
head = i;
}
bitcount = 0;
incoming = 0;
}
}
static inline uint8_t get_scan_code(void)
{
uint8_t c, i;
i = tail;
if (i == head) return 0;
i++;
if (i >= BUFFER_SIZE) i = 0;
c = buffer[i];
tail = i;
return c;
}
#define BREAK 0x01
#define MODIFIER 0x02
#define SHIFT_L 0x04
#define SHIFT_R 0x08
#define ALTGR 0x10
#define CTRL 0x20
void get_ps2_scan_code(KeyEvent* evt){
static uint8_t state=0;
uint8_t s =0;
evt->code = 0;
evt->state = 1;
while(1){
s = get_scan_code();
if(!s)
break;
else if (s == 0xF0)
state |= BREAK;
else if (0xE0 == s)
state |= MODIFIER;
else{
evt->code = s;
evt->state = !(state & BREAK);
evt->mod = (state & MODIFIER);
state &= ~(BREAK | MODIFIER);
break;
}
}
}
bool PS2Events::eventAvailable() {
if(0 != EventBuffer.code)
return true;
get_ps2_scan_code(&EventBuffer);
if(0 != EventBuffer.code)
return true;
return false;
}
void PS2Events::readEvent(KeyEvent* evt){
if(0 != EventBuffer.code){
evt->code = EventBuffer.code;
evt->state = EventBuffer.state;
evt->mod = EventBuffer.mod;
EventBuffer.code = 0;
}
else{
get_ps2_scan_code(evt);
}
}
PS2Events::PS2Events() {
// nothing to do here, begin() does it all
}
void PS2Events::begin(uint8_t data_pin, uint8_t irq_pin) {
uint8_t irq_num=0;
DataPin = data_pin;
EventBuffer.code = 0;
EventBuffer.state = 1;
EventBuffer.mod =0;
// initialize the pins
#ifdef INPUT_PULLUP
pinMode(irq_pin, INPUT_PULLUP);
pinMode(data_pin, INPUT_PULLUP);
#else
pinMode(irq_pin, INPUT);
digitalWrite(irq_pin, HIGH);
pinMode(data_pin, INPUT);
digitalWrite(data_pin, HIGH);
#endif
switch(irq_pin) {
#ifdef CORE_INT0_PIN
case CORE_INT0_PIN:
irq_num = 0;
break;
#endif
#ifdef CORE_INT1_PIN
case CORE_INT1_PIN:
irq_num = 1;
break;
#endif
#ifdef CORE_INT2_PIN
case CORE_INT2_PIN:
irq_num = 2;
break;
#endif
#ifdef CORE_INT3_PIN
case CORE_INT3_PIN:
irq_num = 3;
break;
#endif
#ifdef CORE_INT4_PIN
case CORE_INT4_PIN:
irq_num = 4;
break;
#endif
#ifdef CORE_INT5_PIN
case CORE_INT5_PIN:
irq_num = 5;
break;
#endif
#ifdef CORE_INT6_PIN
case CORE_INT6_PIN:
irq_num = 6;
break;
#endif
#ifdef CORE_INT7_PIN
case CORE_INT7_PIN:
irq_num = 7;
break;
#endif
default:
irq_num = 0;
break;
}
head = 0;
tail = 0;
attachInterrupt(irq_num, ps2interrupt, FALLING);
}