Serial Wombat Arduino Library
Loading...
Searching...
No Matches
SerialWombatPS2Keyboard.h
Go to the documentation of this file.
1#pragma once
2
3/*
4Copyright 2023 Broadwell Consulting Inc.
5
6"Serial Wombat" is a registered trademark of Broadwell Consulting Inc. in
7the United States. See SerialWombat.com for usage guidance.
8
9Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26*/
27
28#include <stdint.h>
29#include "Stream.h"
30#include "SerialWombat.h"
33
34
35typedef enum
36{
38 SCANCODE_1 = 0x16,
39 SCANCODE_2 = 0x1E,
40 SCANCODE_3 = 0x26,
41 SCANCODE_4 = 0x25,
42 SCANCODE_5 = 0x2E,
43 SCANCODE_6 = 0x36,
44 SCANCODE_7 = 0x3D,
45 SCANCODE_8 = 0x3E,
46 SCANCODE_9 = 0x46,
47 SCANCODE_0 = 0x45,
52 SCANCODE_Q = 0x15,
53 SCANCODE_W = 0x1D,
54 SCANCODE_E = 0x24,
55 SCANCODE_R = 0x2D,
56 SCANCODE_T = 0x2C,
57 SCANCODE_Y = 0x35,
58 SCANCODE_U = 0x3C,
59 SCANCODE_I = 0x43,
60 SCANCODE_O = 0x44,
61 SCANCODE_P = 0x4D,
65 SCANCODE_A = 0x1C,
66 SCANCODE_S = 0x1B,
67 SCANCODE_D = 0x23,
68 SCANCODE_G = 0x34,
69 SCANCODE_H = 0x33,
70 SCANCODE_J = 0x3B,
71 SCANCODE_K = 0x42,
72 SCANCODE_L = 0x4B,
77 SCANCODE_Z = 0x1A,
78 SCANCODE_X = 0x22,
79 SCANCODE_C = 0x21,
80 SCANCODE_V = 0x2A,
81 SCANCODE_B = 0x32,
82 SCANCODE_N = 0x31,
83 SCANCODE_M = 0x3A,
137
138
180
182 public Stream, public SerialWombatPin
183{
184public:
199 int16_t begin(uint8_t clockPin, uint8_t dataPin, uint8_t bufferMode = 0, uint8_t queueMode = 0, uint16_t queueAddress = 0xFFFF, uint8_t pullUpDown = 0)
200 {
201 _pin = clockPin;
203
204 uint8_t tx[] = { (uint8_t)SerialWombatCommands::CONFIGURE_PIN_MODE0,
205 _pin,
206 (uint8_t)_pinMode ,
207 dataPin,
208 queueMode,
209 bufferMode,
210 0x55,
211 pullUpDown};
212 int16_t result = _sw.sendPacket(tx);
213 if (result < 0)
214 {
215 return result;
216 }
217
218 if (queueAddress != 0xFFFF)
219 {
220 uint8_t tx6[] = { (uint8_t)SerialWombatCommands::CONFIGURE_PIN_MODE6,
221 _pin,
222 _pinMode,
223 SW_LE16(queueAddress),
224 0x55,
225 0x55,
226 0x55 };
227
228 return _sw.sendPacket(tx6);
229 }
230 return (result);
231 }
232
233
234
240 {
241 uint8_t tx[8] = { 201, _pin, _pinMode, 0,0x55,0x55,0x55,0x55 };
242 uint8_t rx[8];
243 _sw.sendPacket(tx, rx);
244 return (rx[4]);
245 }
246
250 int read()
251 {
252 uint8_t tx[8] = { 202, _pin,_pinMode, 1,0x55,0x55,0x55,0x55 };
253 uint8_t rx[8];
254 if (_sw.sendPacket(tx, rx) < 0)
255 {
256 return -1;
257 }
258
259 if (rx[3] != 0)
260 {
261 return (rx[4]);
262 }
263 else
264 {
265 return (-1);
266 }
267 }
268
271 void flush()
272 {
273
274 }
275
280 int peek()
281 {
282 uint8_t tx[8] = { 203, _pin,_pinMode,0x55,0x55,0x55,0x55,0x55 };
283 uint8_t rx[8];
284 _sw.sendPacket(tx, rx);
285 if (rx[4] > 0)
286 {
287 return (rx[5]);
288 }
289 else
290 {
291 return (-1);
292 }
293 }
294
302 size_t write(uint8_t data)
303{
304 (void)data; // Avoid compiler warning for unused parameter
305
306 return (1);
307}
308
317 size_t write(const uint8_t* buffer, size_t size)
318{
319 (void)buffer; // Avoid compiler warning for unused parameter
320 return(size);
321}
322
328{
329 return(0);
330}
331
342 size_t readBytes(char* buffer, size_t length)
343 {
344 int index = 0;
345 int bytesAvailable = 0;
346 uint32_t timeoutMillis = millis() + timeout;
347 while (length > 0 && timeoutMillis > millis())
348 {
349 int bytecount = 4;
350 if (length < 4)
351 {
352 bytecount = length;
353 }
354 {
355
356 uint8_t tx[8] = { 202, _pin,_pinMode, (uint8_t)bytecount,0x55,0x55,0x55,0x55 };
357 uint8_t rx[8];
358 _sw.sendPacket(tx, rx);
359 bytesAvailable = rx[3];
360
361 if (bytesAvailable == 0)
362 {
363 continue;
364 }
365 else
366 {
367 timeoutMillis = millis() + timeout;
368 }
369 uint8_t bytesReturned = bytecount;
370 if (rx[3] < bytecount)
371 {
372 bytesReturned = rx[3];
373 }
374 for (int i = 0; i < bytesReturned; ++i)
375 {
376 buffer[index] = rx[i + 4];
377 ++index;
378 --bytesAvailable;
379 --length;
380
381 }
382 }
383
384 }
385 return (index);
386 }
387
388 int16_t readCurrentScanCodes(uint8_t* buffer, uint8_t startValue)
389 {
390 uint8_t tx[8] = { 207, _pin,_pinMode, startValue,0x55,0x55,0x55,0x55 };
391 uint8_t rx[8];
392
393 int16_t result = _sw.sendPacket(tx, rx);
394
395 if (result < 0)
396 {
397 return result;
398 }
399 int count = 0;
400 for (int i = 3; i < 8; ++i)
401 {
402 if (rx[i] != 0)
403 {
404 ++count;
405 }
406 buffer[i - 3] = rx[i];
407 }
408 return count;
409 }
410
414 void setTimeout(long timeout_mS)
415 {
416 if (timeout_mS == 0)
417 {
418 timeout = 0x80000000;
419 }
420 else
421 {
422 timeout = timeout_mS;
423 }
424 }
425
429 uint8_t scanCodeToAscii(uint8_t scanCode, bool shiftActive = false)
430 {
431
432 if (scanCode >= 0x80)
433 {
434 return 0;
435 }
436 //This array is used to convert PS2 Code set 2 codes to Ascii. The first column is unshfited data, the second if shift is active
437 const uint8_t KBSCSet2[][2] =
438 {
439 { ' ' , ' ' }, /* 0 */
440 { ' ' , ' ' }, /* 1 */
441 { ' ' , ' ' }, /* 2 */
442 { ' ' , ' ' }, /* 3 */
443 { ' ' , ' ' }, /* 4 */
444 { ' ' , ' ' }, /* 5 */
445 { ' ' , ' ' }, /* 6 */
446 { ' ' , ' ' }, /* 7 */
447 { ' ' , ' ' }, /* 8 */
448 { ' ' , ' ' }, /* 9 */
449 { ' ' , ' ' }, /* A */
450 { ' ' , ' ' }, /* B */
451 { ' ' , ' ' }, /* C */
452 { 9 , 9 }, /* D */
453 { '`' , '~' }, /* E */
454 { ' ' , ' ' }, /* F */
455 { ' ' , ' ' }, /* 10 */
456 { ' ' , ' ' }, /* 11 */
457 { 0 , 0 }, /* 12 */
458 { ' ' , ' ' }, /* 13 */
459 { ' ' , ' ' }, /* 14 */
460 { 'q' , 'Q' }, /* 15 */
461 { '1' , '!' }, /* 16 */
462 { ' ' , ' ' }, /* 17 */
463 { ' ' , ' ' }, /* 18 */
464 { ' ' , ' ' }, /* 19 */
465 { 'z' , 'Z' }, /* 1A */
466 { 's' , 'S' }, /* 1B */
467 { 'a' , 'A' }, /* 1C */
468 { 'w' , 'W' }, /* 1D */
469 { '2' , '@' }, /* 1E */
470 { ' ' , ' ' }, /* 1F */
471 { ' ' , ' ' }, /* 20 */
472 { 'c' , 'C' }, /* 21 */
473 { 'x' , 'X' }, /* 22 */
474 { 'd' , 'D' }, /* 23 */
475 { 'e' , 'E' }, /* 24 */
476 { '4' , '$' }, /* 25 */
477 { '3' , '#' }, /* 26 */
478 { ' ' , ' ' }, /* 27 */
479 { ' ' , ' ' }, /* 28 */
480 { ' ' , ' ' }, /* 29 - SPACE */
481 { 'v' , 'V' }, /* 2A */
482 { 'f' , 'F' }, /* 2B */
483 { 't' , 'T' }, /* 2C */
484 { 'r' , 'R' }, /* 2D */
485 { '5' , '%' }, /* 2E */
486 { ' ' , ' ' }, /* 2F */
487 { ' ' , ' ' }, /* 30 */
488 { 'n' , 'N' }, /* 31 */
489 { 'b' , 'B' }, /* 32 */
490 { 'h' , 'H' }, /* 33 */
491 { 'g' , 'G' }, /* 34 */
492 { 'y' , 'Y' }, /* 35 */
493 { '6' , '^' }, /* 36 */
494 { ' ' , ' ' }, /* 37 */
495 { ' ' , ' ' }, /* 38 */
496 { ' ' , ' ' }, /* 39 */
497 { 'm' , 'M' }, /* 3A */
498 { 'j' , 'J' }, /* 3B */
499 { 'u' , 'U' }, /* 3C */
500 { '7' , '&' }, /* 3D */
501 { '8' , '*' }, /* 3E */
502 { ' ' , ' ' }, /* 3F */
503 { ' ' , ' ' }, /* 40 */
504 { ',' , '>' }, /* 41 */
505 { 'k' , 'K' }, /* 42 */
506 { 'i' , 'I' }, /* 43 */
507 { 'o' , 'O' }, /* 44 */
508 { '0' , ')' }, /* 45 */
509 { '9' , '(' }, /* 46 */
510 { ' ' , ' ' }, /* 47 */
511 { ' ' , ' ' }, /* 48 */
512 { '.' , '<' }, /* 49 */
513 { '/' , '?' }, /* 4A */
514 { 'l' , 'L' }, /* 4B */
515 { ';' , ':' }, /* 4C */
516 { 'p' , 'P' }, /* 4D */
517 { '-' , '_' }, /* 4E */
518 { ' ' , ' ' }, /* 4F */
519 { ' ' , ' ' }, /* 50 */
520 { ' ' , ' ' }, /* 51 */
521 { '\'' , '"' }, /* 52 */
522 { ' ' , ' ' }, /* 53 */
523 { '[' , '{' }, /* 54 */
524 { '=' , '+' }, /* 55 */
525 { ' ' , ' ' }, /* 56 */
526 { ' ' , ' ' }, /* 57 */
527 { ' ' , ' ' }, /* 58 */
528 { 0 , 0 }, /* 59 */
529 { 0xD , 0xD }, /* 5A */
530 { ']' , '}' }, /* 5B */
531 { ' ' , ' ' }, /* 5C */
532 { '\\' , '|' }, /* 5D */
533 { ' ' , ' ' }, /* 5E */
534 { ' ' , ' ' }, /* 5F */
535 { ' ' , ' ' }, /* 60 */
536 { ' ' , ' ' }, /* 61 */
537 { ' ' , ' ' }, /* 62 */
538 { ' ' , ' ' }, /* 63 */
539 { ' ' , ' ' }, /* 64 */
540 { ' ' , ' ' }, /* 65 */
541 { 8 , 8 }, /* 66 */
542 { ' ' , ' ' }, /* 67 */
543 { ' ' , ' ' }, /* 68 */
544 { '1' , '1' }, /* 69 */
545 { ' ' , ' ' }, /* 6A */
546 { '4' , '4' }, /* 6B */
547 { '7' , '7' }, /* 6C */
548 { ' ' , ' ' }, /* 6D */
549 { ' ' , ' ' }, /* 6E */
550 { ' ' , ' ' }, /* 6F */
551 { '0' , '0' }, /* 70 */
552 { ' ' , ' ' }, /* 71 */
553 { '2' , '2' }, /* 72 */
554 { '5' , '5' }, /* 73 */
555 { '6' , '6' }, /* 74 */
556 { '8' , '8' }, /* 75 */
557 { 0x1B , 0x1B }, /* 76 */
558 { ' ' , ' ' }, /* 77 */
559 { ' ' , ' ' }, /* 78 */
560 { ' ' , ' ' }, /* 79 */
561 { '3' , '3' }, /* 7A */
562 { ' ' , ' ' }, /* 7B */
563 { ' ' , ' ' }, /* 7C */
564 { '9' , '9' }, /* 7D */
565 { ' ' , ' ' }, /* 7E */
566 { ' ' , ' ' }, /* 7F */
567 };
568
569 if (shiftActive)
570 {
571 return ( KBSCSet2[scanCode][ 1]);
572 }
573
574 return ( KBSCSet2[scanCode][0]);
575 }
576
582 bool isKeyPressed(uint8_t scanCode)
583{
584 uint8_t buffer[5];
585 int16_t result = readCurrentScanCodes(buffer, scanCode);
586
587 if (result < 0)
588 {
589 return false;
590 }
591
592 if (buffer[0] == scanCode)
593 {
594 return true;
595 }
596
597 return false;
598
599}
600
602{
603 return isKeyPressed((uint8_t) scanCode);
604}
605
606 uint8_t _pin = 255;
607protected:
608 uint32_t timeout = 1;
609};
610
611
612
613
#define SW_LE16(_a)
Convert a uint16_t to two bytes in little endian format for array initialization.
@ PIN_MODE_PS2KEYBOARD
(32)
@ SCANCODE_RIGHTALT
@ SCANCODE_SEMICOLON
@ SCANCODE_OPENSINGLEQUOTE
@ SCANCODE_RIGHTBRACKET
@ SCANCODE_RIGHTCTRL
@ SCANCODE_DOWNARROW
@ SCANCODE_SPACEBAR
@ SCANCODE_LEFTBRACKET
@ SCANCODE_KPASTERISK
@ SCANCODE_PRINTSCREEN
@ SCANCODE_LEFTSHIFT
@ SCANCODE_RIGHTSHIFT
@ SCANCODE_BACKSPACE
@ SCANCODE_CAPSLOCK
@ SCANCODE_SCROLLLOCK
@ SCANCODE_LEFTCTRL
@ SCANCODE_LEFTARROW
@ SCANCODE_RIGHTARROW
Class for a Serial Wombat chip. Each Serial Wombat chip on a project should have its own instance.
int peek()
Query the SerialWombatPS2Keyboard queue for the next avaialble byte, but don't remove it from the que...
bool isKeyPressed(uint8_t scanCode)
Check to see if a key is currently pressed (pin mode must be configured for bitfield mode)
int16_t readCurrentScanCodes(uint8_t *buffer, uint8_t startValue)
size_t write(uint8_t data)
Write a byte to the SerialWombatPS2Keyboard queue (Does Nothing)
int available()
Queries the SerialWombatPS2Keyboard for number bytes available to read.
size_t write(const uint8_t *buffer, size_t size)
Write bytes to the SerialWombatPS2Keyboard queue (Does nothing)
int read()
Reads a byte from the SerialWombatPS2Keyboard queue.
void setTimeout(long timeout_mS)
implemented to fulfill Stream requirement.
bool isKeyPressed(PS2KeyboardScanCode scanCode)
size_t readBytes(char *buffer, size_t length)
Reads a specified number of bytes from the SerialWombatPS2Keyboard queue queue.
int availableForWrite()
Number of bytes avaialble to write to SerialWombatPS2Keyboard queue. Returns 0.
void flush()
Discard all bytes from the SerialWombatPS2Keyboard queue.
uint8_t scanCodeToAscii(uint8_t scanCode, bool shiftActive=false)
convernts a set 2 Scan Code to Ascii
SerialWombatPS2Keyboard(SerialWombatChip &serialWombat)
Constructor for the SerialWombatPS2Keyboard class.
int16_t begin(uint8_t clockPin, uint8_t dataPin, uint8_t bufferMode=0, uint8_t queueMode=0, uint16_t queueAddress=0xFFFF, uint8_t pullUpDown=0)
Initalize the SerialWombatPS2Keyboard.
SerialWombatChip & _sw
SerialWombatPin(SerialWombatChip &serialWombatChip)
Instantiates a Serial Wombat Pin.