diff --git a/PS2Keyboard.cpp b/PS2Keyboard.cpp index 53bfa1a..e236eea 100644 --- a/PS2Keyboard.cpp +++ b/PS2Keyboard.cpp @@ -4,12 +4,19 @@ Written by Christian Weichel ** Mostly rewritten Paul Stoffregen 2010, 2011 - ** Modified for use beginning with Arduino 13 by L. Abraham Smith, * - ** Modified for easy interrup pin assignement on method begin(datapin,irq_pin). Cuningan ** + ** Modified for use beginning with Arduino 13 by L. Abraham Smith, + ** Modified for easy interrupt pin assignment on method begin(datapin,irq_pin). Cuningan + ** Modified for ESP32/ESP8266 support by Lahiru - for more information you can read the original wiki in arduino.cc - at http://www.arduino.cc/playground/Main/PS2Keyboard - or http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html + For more information: + - https://github.com/lahirunirmalx/PS2Keyboard + - http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html + + Version 3.0 (January 2026) + - ESP32 and ESP8266 platform support + - Improved interrupt handling with IRAM_ATTR for ESP32 + - Caps Lock, Num Lock, Scroll Lock LED support + - Code cleanup and optimization Version 2.4 (March 2013) - Support Teensy 3.0, Arduino Due, Arduino Leonardo & other boards @@ -24,7 +31,6 @@ 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 @@ -53,55 +59,149 @@ #define BUFFER_SIZE 45 static volatile uint8_t buffer[BUFFER_SIZE]; static volatile uint8_t head, tail; -static uint8_t DataPin; +static uint8_t dataPin; +static uint8_t IRQPin; static uint8_t CharBuffer=0; static uint8_t UTF8next=0; static const PS2Keymap_t *keymap=NULL; +static bool capsLockOn = false; +static bool numLockOn = false; +static bool scrollLockOn = false; +static byte ledState = 0; -// The ISR for the external interrupt -void ps2interrupt(void) +// LED control command for PS/2 keyboard +#define LED_CONTROL 0xED + +// ESP32 requires IRAM_ATTR for interrupt handlers +#if defined(ESP32) + #define SUPPORT_IRAM_ATTR IRAM_ATTR +#else + #define SUPPORT_IRAM_ATTR +#endif + +// Parity check +// Return true for odd parity. +static bool parityCheck(uint16_t data) { - 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; - } + uint8_t count = 0; + for (int i = 0; i < 10; i++) { + count += (data >> i) & 1; + } + return count % 2 != 0; } +/* +code taken from https://karooza.net/how-to-interface-a-ps2-keyboard +parity was needed and the writing should have done on rising edeg not in falling +*/ +static void sendPS2Command(uint8_t cmdCode) { + uint16_t cmd = cmdCode; // Cast to 16-bit to add parity and stop bits -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; + // Add parity bit if not already set + if (!parityCheck(cmd)) { + cmd |= 0x0100; + } + + // Add stop bit + cmd |= 0x0200; + + // Set clock and data pins to output mode + pinMode(IRQPin, OUTPUT); + pinMode(dataPin, OUTPUT); + + // Start Request to Send by pulling clock low for 100us + digitalWrite(IRQPin, LOW); + unsigned long startMicros = micros(); + while (micros() - startMicros < 100); // Wait for 100us + + // Pull data low to send the start bit + digitalWrite(dataPin, LOW); + startMicros = micros(); + while (micros() - startMicros < 20); // Wait for 20us + + // Release clock line, allowing it to go high + pinMode(IRQPin, INPUT_PULLUP); + + // Send 8 data bits, 1 parity bit, and 1 stop bit + for (int i = 0; i < 10; i++) { + // Wait for keyboard to take clock low (start of bit transmission) + while (digitalRead(IRQPin) > 0); + + // Write the current bit to the data line + digitalWrite(dataPin, cmd & 0x0001); + cmd >>= 1; // Shift to the next bit + + // Wait for the keyboard to take clock high, indicating bit has been sampled + while (digitalRead(IRQPin) < 1); + } + + // Release data line (high) for the stop bit + pinMode(dataPin, INPUT_PULLUP); + + // Wait for keyboard to acknowledge by taking clock low + while (digitalRead(IRQPin) > 0); + + // Wait for keyboard ACK by checking data line goes low + while (digitalRead(dataPin) > 0); + + // Reset pins to input mode with pull-up resistors +#ifdef INPUT_PULLUP + pinMode(IRQPin, INPUT_PULLUP); + pinMode(dataPin, INPUT_PULLUP); +#else + pinMode(IRQPin, INPUT); + digitalWrite(IRQPin, HIGH); + pinMode(dataPin, INPUT); + digitalWrite(dataPin, HIGH); +#endif +} + +static void updateLEDs(byte command) { + sendPS2Command(LED_CONTROL); + sendPS2Command(command); +} + +// The ISR for the external interrupt +void SUPPORT_IRAM_ATTR ps2interrupt(void) { + static uint8_t bitCount = 0; + static uint8_t incoming = 0; + static uint32_t prevMillis = 0; + uint32_t nowMillis; + uint8_t bitPos, val; + + val = digitalRead(dataPin); + nowMillis = millis(); + if (nowMillis - prevMillis > 250) { + bitCount = 0; + incoming = 0; + } + prevMillis = nowMillis; + bitPos = bitCount - 1; + if (bitPos <= 7) { + incoming |= (val << bitPos); + } + 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 getScanCode(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; } // http://www.quadibloc.com/comp/scan.htm @@ -152,356 +252,121 @@ const PROGMEM PS2Keymap_t PS2Keymap_US = { 0 }; - -const PROGMEM PS2Keymap_t PS2Keymap_German = { - // without shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, '^', 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'q', '1', 0, - 0, 0, 'y', 's', 'a', 'w', '2', 0, - 0, 'c', 'x', 'd', 'e', '4', '3', 0, - 0, ' ', 'v', 'f', 't', 'r', '5', 0, - 0, 'n', 'b', 'h', 'g', 'z', '6', 0, - 0, 0, 'm', 'j', 'u', '7', '8', 0, - 0, ',', 'k', 'i', 'o', '0', '9', 0, - 0, '.', '-', 'l', PS2_o_DIAERESIS, 'p', PS2_SHARP_S, 0, - 0, 0, PS2_a_DIAERESIS, 0, PS2_u_DIAERESIS, '\'', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '+', 0, '#', 0, 0, - 0, '<', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - // with shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, PS2_DEGREE_SIGN, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'Q', '!', 0, - 0, 0, 'Y', 'S', 'A', 'W', '"', 0, - 0, 'C', 'X', 'D', 'E', '$', PS2_SECTION_SIGN, 0, - 0, ' ', 'V', 'F', 'T', 'R', '%', 0, - 0, 'N', 'B', 'H', 'G', 'Z', '&', 0, - 0, 0, 'M', 'J', 'U', '/', '(', 0, - 0, ';', 'K', 'I', 'O', '=', ')', 0, - 0, ':', '_', 'L', PS2_O_DIAERESIS, 'P', '?', 0, - 0, 0, PS2_A_DIAERESIS, 0, PS2_U_DIAERESIS, '`', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '*', 0, '\'', 0, 0, - 0, '>', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - 1, - // with altgr - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, 0, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, '@', 0, 0, - 0, 0, 0, 0, 0, 0, PS2_SUPERSCRIPT_TWO, 0, - 0, 0, 0, 0, PS2_CURRENCY_SIGN, 0, PS2_SUPERSCRIPT_THREE, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, PS2_MICRO_SIGN, 0, 0, '{', '[', 0, - 0, 0, 0, 0, 0, '}', ']', 0, - 0, 0, 0, 0, 0, 0, '\\', 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '~', 0, '#', 0, 0, - 0, '|', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 } -}; - - -const PROGMEM PS2Keymap_t PS2Keymap_French = { - // without shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, PS2_SUPERSCRIPT_TWO, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'a', '&', 0, - 0, 0, 'w', 's', 'q', 'z', PS2_e_ACUTE, 0, - 0, 'c', 'x', 'd', 'e', '\'', '"', 0, - 0, ' ', 'v', 'f', 't', 'r', '(', 0, - 0, 'n', 'b', 'h', 'g', 'y', '-', 0, - 0, 0, ',', 'j', 'u', PS2_e_GRAVE, '_', 0, - 0, ';', 'k', 'i', 'o', PS2_a_GRAVE, PS2_c_CEDILLA, 0, - 0, ':', '!', 'l', 'm', 'p', ')', 0, - 0, 0, PS2_u_GRAVE, 0, '^', '=', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '$', 0, '*', 0, 0, - 0, '<', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - // with shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, 0, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'A', '1', 0, - 0, 0, 'W', 'S', 'Q', 'Z', '2', 0, - 0, 'C', 'X', 'D', 'E', '4', '3', 0, - 0, ' ', 'V', 'F', 'T', 'R', '5', 0, - 0, 'N', 'B', 'H', 'G', 'Y', '6', 0, - 0, 0, '?', 'J', 'U', '7', '8', 0, - 0, '.', 'K', 'I', 'O', '0', '9', 0, - 0, '/', PS2_SECTION_SIGN, 'L', 'M', 'P', PS2_DEGREE_SIGN, 0, - 0, 0, '%', 0, PS2_DIAERESIS, '+', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, PS2_POUND_SIGN, 0, PS2_MICRO_SIGN, 0, 0, - 0, '>', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - 1, - // with altgr - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, 0, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, '@', 0, 0, - 0, 0, 0, 0, 0, 0, '~', 0, - 0, 0, 0, 0, 0 /*PS2_EURO_SIGN*/, '{', '#', 0, - 0, 0, 0, 0, 0, 0, '[', 0, - 0, 0, 0, 0, 0, 0, '|', 0, - 0, 0, 0, 0, 0, '`', '\\', 0, - 0, 0, 0, 0, 0, '@', '^', 0, - 0, 0, 0, 0, 0, 0, ']', 0, - 0, 0, 0, 0, 0, 0, '}', 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, PS2_CURRENCY_SIGN, 0, '#', 0, 0, - 0, '|', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 } -}; - -const PROGMEM PS2Keymap_t PS2Keymap_Spanish = { - // without shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, PS2_MASCULINE_ORDINAL, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'q', '1', 0, - 0, 0, 'z', 's', 'a', 'w', '2', 0, - 0, 'c', 'x', 'd', 'e', '4', '3', 0, - 0, ' ', 'v', 'f', 't', 'r', '5', 0, - 0, 'n', 'b', 'h', 'g', 'y', '6', 0, - 0, 0, 'm', 'j', 'u', '7', '8', 0, - 0, ',', 'k', 'i', 'o', '0', '9', 0, - 0, '.', '-', 'l', 'n', 'p', '\'', 0, - 0, 0, PS2_ACUTE_ACCENT, 0, '`', PS2_INVERTED_EXCLAMATION, 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '+', 0, PS2_c_CEDILLA, 0, 0, - 0, '<', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - // with shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, PS2_FEMININE_ORDINAL, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'Q', '!', 0, - 0, 0, 'Z', 'S', 'A', 'W', '\"', 0, - 0, 'C', 'X', 'D', 'E', '$', PS2_MIDDLE_DOT, 0, - 0, ' ', 'V', 'F', 'T', 'R', '%', 0, - 0, 'N', 'B', 'H', 'G', 'Y', '&', 0, - 0, 0, 'M', 'J', 'U', '/', '(', 0, - 0, ';', 'K', 'I', 'O', '=', ')', 0, - 0, ':', '_', 'L', 'N', 'P', '?', 0, - 0, 0, PS2_DIAERESIS, 0, '^', PS2_INVERTED_QUESTION_MARK, 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '*', 0, PS2_C_CEDILLA, 0, 0, - 0, '>', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - 1, - // with altgr - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, '\\', 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'q', '|', 0, - 0, 0, 'z', 's', 'a', 'w', '@', 0, - 0, 'c', 'x', 'd', PS2_EURO_SIGN, '~', '#', 0, - 0, ' ', 'v', 'f', 't', 'r', '5', 0, - 0, 'n', 'b', 'h', 'g', 'y', PS2_NOT_SIGN, 0, - 0, 0, 'm', 'j', 'u', '7', '8', 0, - 0, ',', 'k', 'i', 'o', '0', '9', 0, - 0, '.', '-', 'l', 'n', 'p', '\'', 0, - 0, 0, '{', 0, '[', PS2_INVERTED_EXCLAMATION, 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, ']', 0, '}', 0, 0, - 0, '|', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 } -}; - -const PROGMEM PS2Keymap_t PS2Keymap_Italian = { - // without shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, '\\', 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'q', '1', 0, - 0, 0, 'z', 's', 'a', 'w', '2', 0, - 0, 'c', 'x', 'd', 'e', '4', '3', 0, - 0, ' ', 'v', 'f', 't', 'r', '5', 0, - 0, 'n', 'b', 'h', 'g', 'y', '6', 0, - 0, 0, 'm', 'j', 'u', '7', '8', 0, - 0, ',', 'k', 'i', 'o', '0', '9', 0, - 0, '.', '-', 'l', PS2_o_GRAVE, 'p', '\'', 0, - 0, 0, PS2_a_GRAVE, 0, PS2_e_GRAVE, PS2_i_GRAVE, 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '+', 0, PS2_u_GRAVE, 0, 0, - 0, '<', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - // with shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, '|', 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'Q', '!', 0, - 0, 0, 'Z', 'S', 'A', 'W', '\"', 0, - 0, 'C', 'X', 'D', 'E', '$', PS2_POUND_SIGN, 0, - 0, ' ', 'V', 'F', 'T', 'R', '%', 0, - 0, 'N', 'B', 'H', 'G', 'Y', '&', 0, - 0, 0, 'M', 'J', 'U', '/', '(', 0, - 0, ';', 'K', 'I', 'O', '=', ')', 0, - 0, ':', '_', 'L', PS2_c_CEDILLA, 0, '?', 0, - 0, 0, PS2_DEGREE_SIGN, 0, PS2_e_ACUTE, '^', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '*', 0, PS2_SECTION_SIGN, 0, 0, - 0, '>', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - 1, - // with altgr - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, PS2_NOT_SIGN, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'q', PS2_SUPERSCRIPT_ONE, 0, - 0, 0, 'z', 's', 'a', 'w', PS2_SUPERSCRIPT_TWO, 0, - 0, 'c', 'x', 'd', PS2_EURO_SIGN, PS2_FRACTION_ONE_QUARTER, PS2_SUPERSCRIPT_THREE, 0, - 0, ' ', 'v', 'f', 't', 'r', PS2_FRACTION_ONE_HALF, 0, - 0, 'n', 'b', 'h', 'g', 'y', PS2_NOT_SIGN, 0, - 0, 0, 'm', 'j', 'u', '{', '[', 0, - 0, ',', 'k', 'i', 'o', '}', ']', 0, - 0, '.', '-', 'l', '@', 'p', '\'', 0, - 0, 0, '#', 0, '[', '~', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, ']', 0, 0, 0, 0, - 0, PS2_LEFT_DOUBLE_ANGLE_QUOTE, 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 } -}; - -const PROGMEM PS2Keymap_t PS2Keymap_UK = { -// https://github.com/PaulStoffregen/PS2Keyboard/issues/15 - // without shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, '`', 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'q', '1', 0, - 0, 0, 'z', 's', 'a', 'w', '2', 0, - 0, 'c', 'x', 'd', 'e', '4', '3', 0, - 0, ' ', 'v', 'f', 't', 'r', '5', 0, - 0, 'n', 'b', 'h', 'g', 'y', '6', 0, - 0, 0, 'm', 'j', 'u', '7', '8', 0, - 0, ',', 'k', 'i', 'o', '0', '9', 0, - 0, '.', '/', 'l', ';', 'p', '-', 0, - 0, 0, '\'', 0, '[', '=', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, ']', 0, '#', 0, 0, - 0, '\\', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - // with shift - {0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12, - 0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, 172 /* ¬ */, 0, - 0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'Q', '!', 0, - 0, 0, 'Z', 'S', 'A', 'W', '"', 0, - 0, 'C', 'X', 'D', 'E', '$', 163 /* £ */, 0, - 0, ' ', 'V', 'F', 'T', 'R', '%', 0, - 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, - 0, 0, 'M', 'J', 'U', '&', '*', 0, - 0, '<', 'K', 'I', 'O', ')', '(', 0, - 0, '>', '?', 'L', ':', 'P', '_', 0, - 0, 0, '@', 0, '{', '+', 0, 0, - 0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '}', 0, '~', 0, 0, - 0, '|', 0, 0, 0, 0, PS2_BACKSPACE, 0, - 0, '1', 0, '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/, - PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0, - 0, 0, 0, PS2_F7 }, - 0 -}; - +// State machine flags for scan code processing #define BREAK 0x01 #define MODIFIER 0x02 #define SHIFT_L 0x04 #define SHIFT_R 0x08 #define ALTGR 0x10 -static char get_iso8859_code(void) -{ - static uint8_t state=0; - uint8_t s; - char c; - - while (1) { - s = get_scan_code(); - if (!s) return 0; - if (s == 0xF0) { - state |= BREAK; - } else if (s == 0xE0) { - state |= MODIFIER; - } else { - if (state & BREAK) { - if (s == 0x12) { - state &= ~SHIFT_L; - } else if (s == 0x59) { - state &= ~SHIFT_R; - } else if (s == 0x11 && (state & MODIFIER)) { - state &= ~ALTGR; - } - // CTRL, ALT & WIN keys could be added - // but is that really worth the overhead? - state &= ~(BREAK | MODIFIER); - continue; - } - if (s == 0x12) { - state |= SHIFT_L; - continue; - } else if (s == 0x59) { - state |= SHIFT_R; - continue; - } else if (s == 0x11 && (state & MODIFIER)) { - state |= ALTGR; - } - c = 0; - if (state & MODIFIER) { - switch (s) { - case 0x70: c = PS2_INSERT; break; - case 0x6C: c = PS2_HOME; break; - case 0x7D: c = PS2_PAGEUP; break; - case 0x71: c = PS2_DELETE; break; - case 0x69: c = PS2_END; break; - case 0x7A: c = PS2_PAGEDOWN; break; - case 0x75: c = PS2_UPARROW; break; - case 0x6B: c = PS2_LEFTARROW; break; - case 0x72: c = PS2_DOWNARROW; break; - case 0x74: c = PS2_RIGHTARROW; break; - case 0x4A: c = '/'; break; - case 0x5A: c = PS2_ENTER; break; - default: break; - } - } else if ((state & ALTGR) && pgm_read_byte(keymap->uses_altgr)) { - if (s < PS2_KEYMAP_SIZE) - c = pgm_read_byte(keymap->altgr + s); - } else if (state & (SHIFT_L | SHIFT_R)) { - if (s < PS2_KEYMAP_SIZE) - c = pgm_read_byte(keymap->shift + s); - } else { - if (s < PS2_KEYMAP_SIZE) - c = pgm_read_byte(keymap->noshift + s); - } - state &= ~(BREAK | MODIFIER); - if (c) return c; - } - } +// LED state bit flags +#define SCROLL_LOCK 0x01 +#define NUM_LOCK 0x02 +#define CAPS_LOCK 0x04 + +static char get_iso8859_code(void) { + static uint8_t state = 0; + uint8_t scanCode; + char character; + + while (1) { + // Retrieve the scan code + scanCode = getScanCode(); + if (!scanCode) return 0; // No scan code available + + // Handle special cases for scan codes + if (scanCode == 0xF0) { + state |= BREAK; // Set BREAK state + } else if (scanCode == 0xE0) { + state |= MODIFIER; // Set MODIFIER state for extended keys + } else { + // Handle key release (BREAK state) + if (state & BREAK) { + if (scanCode == 0x12) { + state &= ~SHIFT_L; // Release Left Shift + } else if (scanCode == 0x59) { + state &= ~SHIFT_R; // Release Right Shift + } else if (scanCode == 0x11 && (state & MODIFIER)) { + state &= ~ALTGR; // Release AltGr + } + // Reset states and continue to next scan code + state &= ~(BREAK | MODIFIER); + continue; + } + + // Handle key press events for modifiers and locks + if (scanCode == 0x12) { + state |= SHIFT_L; // Left Shift pressed + continue; + } else if (scanCode == 0x59) { + state |= SHIFT_R; // Right Shift pressed + continue; + } else if (scanCode == 0x11 && (state & MODIFIER)) { + state |= ALTGR; // AltGr pressed + } else if (scanCode == 0x58) { + capsLockOn = !capsLockOn; // Toggle Caps Lock + ledState = capsLockOn ? (ledState | CAPS_LOCK) : (ledState & ~CAPS_LOCK); + updateLEDs(ledState); + } else if (scanCode == 0x77) { + numLockOn = !numLockOn; // Toggle Num Lock + ledState = numLockOn ? (ledState | NUM_LOCK) : (ledState & ~NUM_LOCK); + updateLEDs(ledState); + } else if (scanCode == 0x7E) { + scrollLockOn = !scrollLockOn; // Toggle Scroll Lock + ledState = scrollLockOn ? (ledState | SCROLL_LOCK) : (ledState & ~SCROLL_LOCK); + updateLEDs(ledState); + } + + // Process scan codes based on the current state + character = 0; + if (state & MODIFIER) { + // Handle special keys with modifier (like arrow keys) + switch (scanCode) { + case 0x70: character = PS2_INSERT; break; + case 0x6C: character = PS2_HOME; break; + case 0x7D: character = PS2_PAGEUP; break; + case 0x71: character = PS2_DELETE; break; + case 0x69: character = PS2_END; break; + case 0x7A: character = PS2_PAGEDOWN; break; + case 0x75: character = PS2_UPARROW; break; + case 0x6B: character = PS2_LEFTARROW; break; + case 0x72: character = PS2_DOWNARROW; break; + case 0x74: character = PS2_RIGHTARROW; break; + case 0x4A: character = '/'; break; + case 0x5A: character = PS2_ENTER; break; + default: break; + } + } else if ((state & ALTGR) && pgm_read_byte(keymap->uses_altgr)) { + // Handle AltGr key combinations + if (scanCode < PS2_KEYMAP_SIZE) { + character = pgm_read_byte(keymap->altgr + scanCode); + } + } else if (scanCode < PS2_KEYMAP_SIZE) { + // Caps Lock affects only alphabetic keys (a-z). For digits, + // punctuation and function keys, Shift is the sole modifier. + // Detect "letter" by inspecting the unshifted entry rather + // than carrying a parallel flag table. + bool shift_active = (state & (SHIFT_L | SHIFT_R)) != 0; + uint8_t ns = pgm_read_byte(keymap->noshift + scanCode); + bool is_alpha = (ns >= 'a' && ns <= 'z'); + bool effective_shift = shift_active ^ (is_alpha && capsLockOn); + character = effective_shift + ? pgm_read_byte(keymap->shift + scanCode) + : ns; + } + + // Reset the states for the next scan code processing + state &= ~(BREAK | MODIFIER); + + // Return the character if one was generated + if (character) return character; + } + } } + + + bool PS2Keyboard::available() { if (CharBuffer || UTF8next) return true; CharBuffer = get_iso8859_code(); @@ -516,7 +381,7 @@ void PS2Keyboard::clear() { uint8_t PS2Keyboard::readScanCode(void) { - return get_scan_code(); + return getScanCode(); } int PS2Keyboard::read() { @@ -556,10 +421,10 @@ PS2Keyboard::PS2Keyboard() { // nothing to do here, begin() does it all } -void PS2Keyboard::begin(uint8_t data_pin, uint8_t irq_pin, const PS2Keymap_t &map) { - uint8_t irq_num=255; - - DataPin = data_pin; +void PS2Keyboard::begin(uint8_t data_pin, uint8_t irq_pin, const PS2Keymap_t &map) { + uint8_t irq_num = irq_pin; + IRQPin= irq_pin; + dataPin = data_pin; keymap = ↦ // initialize the pins @@ -571,138 +436,10 @@ void PS2Keyboard::begin(uint8_t data_pin, uint8_t irq_pin, const PS2Keymap_t &ma digitalWrite(irq_pin, HIGH); pinMode(data_pin, INPUT); digitalWrite(data_pin, HIGH); -#endif - -#ifdef CORE_INT_EVERY_PIN - irq_num = irq_pin; - -#else - 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 - #ifdef CORE_INT8_PIN - case CORE_INT8_PIN: - irq_num = 8; - break; - #endif - #ifdef CORE_INT9_PIN - case CORE_INT9_PIN: - irq_num = 9; - break; - #endif - #ifdef CORE_INT10_PIN - case CORE_INT10_PIN: - irq_num = 10; - break; - #endif - #ifdef CORE_INT11_PIN - case CORE_INT11_PIN: - irq_num = 11; - break; - #endif - #ifdef CORE_INT12_PIN - case CORE_INT12_PIN: - irq_num = 12; - break; - #endif - #ifdef CORE_INT13_PIN - case CORE_INT13_PIN: - irq_num = 13; - break; - #endif - #ifdef CORE_INT14_PIN - case CORE_INT14_PIN: - irq_num = 14; - break; - #endif - #ifdef CORE_INT15_PIN - case CORE_INT15_PIN: - irq_num = 15; - break; - #endif - #ifdef CORE_INT16_PIN - case CORE_INT16_PIN: - irq_num = 16; - break; - #endif - #ifdef CORE_INT17_PIN - case CORE_INT17_PIN: - irq_num = 17; - break; - #endif - #ifdef CORE_INT18_PIN - case CORE_INT18_PIN: - irq_num = 18; - break; - #endif - #ifdef CORE_INT19_PIN - case CORE_INT19_PIN: - irq_num = 19; - break; - #endif - #ifdef CORE_INT20_PIN - case CORE_INT20_PIN: - irq_num = 20; - break; - #endif - #ifdef CORE_INT21_PIN - case CORE_INT21_PIN: - irq_num = 21; - break; - #endif - #ifdef CORE_INT22_PIN - case CORE_INT22_PIN: - irq_num = 22; - break; - #endif - #ifdef CORE_INT23_PIN - case CORE_INT23_PIN: - irq_num = 23; - break; - #endif - } -#endif - +#endif head = 0; tail = 0; + irq_num = digitalPinToInterrupt(irq_pin); if (irq_num < 255) { attachInterrupt(irq_num, ps2interrupt, FALLING); } diff --git a/PS2Keyboard.h b/PS2Keyboard.h index 4931e37..7f26fb3 100644 --- a/PS2Keyboard.h +++ b/PS2Keyboard.h @@ -4,8 +4,9 @@ Written by Christian Weichel ** Mostly rewritten Paul Stoffregen , June 2010 - ** Modified for use with Arduino 13 by L. Abraham Smith, * - ** Modified for easy interrup pin assignement on method begin(datapin,irq_pin). Cuningan ** + ** Modified for use with Arduino 13 by L. Abraham Smith, + ** Modified for easy interrupt pin assignment on method begin(datapin,irq_pin). Cuningan + ** Modified for ESP32/ESP8266 support by Lahiru This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -25,12 +26,9 @@ #ifndef PS2Keyboard_h #define PS2Keyboard_h + +#include // for attachInterrupt, FALLING -#if defined(ARDUINO) && ARDUINO >= 100 -#include "Arduino.h" // for attachInterrupt, FALLING -#else -#include "WProgram.h" -#endif #include "utility/int_pins.h" @@ -180,12 +178,8 @@ typedef struct { } PS2Keymap_t; +// US keyboard layout (default) extern const PROGMEM PS2Keymap_t PS2Keymap_US; -extern const PROGMEM PS2Keymap_t PS2Keymap_German; -extern const PROGMEM PS2Keymap_t PS2Keymap_French; -extern const PROGMEM PS2Keymap_t PS2Keymap_Spanish; -extern const PROGMEM PS2Keymap_t PS2Keymap_Italian; -extern const PROGMEM PS2Keymap_t PS2Keymap_UK; /** @@ -217,7 +211,7 @@ class PS2Keyboard { static void clear(); /** - * Retutns ps2 scan code. + * Returns the raw PS/2 scan code. */ static uint8_t readScanCode(void); diff --git a/README.md b/README.md index 931f685..f1c7e90 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,194 @@ -#PS/2 Keyboard Library# +# PS2Keyboard Library -PS2Keyboard allows you to use a keyboard for user input. +[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](https://www.gnu.org/licenses/lgpl-2.1) +[![Version](https://img.shields.io/badge/version-3.0.0-green.svg)](https://github.com/lahirunirmalx/PS2Keyboard) -http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html +A PS/2 keyboard library for Arduino, Teensy, ESP32, and ESP8266 platforms. -![](http://www.pjrc.com/teensy/td_libs_PS2Keyboard.jpg) +## Features + +- **Multi-platform support**: Arduino (Uno, Mega, Due, Leonardo), Teensy, ESP32, ESP8266 +- **Interrupt-driven**: Efficient interrupt-based input handling +- **Lock key support**: Caps Lock, Num Lock, and Scroll Lock with LED indicators +- **Easy to use**: Simple API with `begin()`, `available()`, and `read()` methods +- **US keyboard layout**: Standard US QWERTY layout included + +## Installation + +### Arduino IDE + +1. Download this repository as a ZIP file +2. In Arduino IDE: `Sketch` → `Include Library` → `Add .ZIP Library...` +3. Select the downloaded ZIP file + +### PlatformIO + +Add the following to your `platformio.ini`: + +```ini +lib_deps = + https://github.com/lahirunirmalx/PS2Keyboard +``` + +## Wiring + +Connect your PS/2 keyboard to your microcontroller: + +| PS/2 Pin | Signal | Connect To | +|----------|--------|------------| +| 1 | Data | Data Pin (configurable) | +| 3 | GND | GND | +| 4 | VCC | 5V | +| 5 | Clock | IRQ Pin (configurable) | + +> **Note**: PS/2 keyboards require 5V power. Some boards may need level shifters for the data lines. + +## Quick Start + +```cpp +#include + +const int DataPin = 8; +const int IRQpin = 5; + +PS2Keyboard keyboard; + +void setup() { + Serial.begin(115200); + keyboard.begin(DataPin, IRQpin); + Serial.println("PS/2 Keyboard Ready"); +} + +void loop() { + if (keyboard.available()) { + char c = keyboard.read(); + + if (c == PS2_ENTER) { + Serial.println(); + } else if (c == PS2_TAB) { + Serial.print("[Tab]"); + } else if (c == PS2_ESC) { + Serial.print("[ESC]"); + } else if (c == PS2_BACKSPACE) { + Serial.print("[Backspace]"); + } else { + Serial.print(c); + } + } +} +``` + +## Valid IRQ Pins + +| Board | Valid IRQ Pins | +|-------|----------------| +| Arduino Uno | 2, 3 | +| Arduino Mega | 2, 3, 18, 19, 20, 21 | +| Arduino Due | All pins (except 13) | +| Arduino Leonardo | 0, 1, 2, 3 | +| Teensy 3.x/4.x | All digital pins | +| Teensy 2.0 | 5, 6, 7, 8 | +| ESP32 | All GPIO pins | +| ESP8266 | All GPIO pins | + +## API Reference + +### Methods + +| Method | Description | +|--------|-------------| +| `begin(dataPin, irqPin)` | Initialize the keyboard with data and clock pins | +| `begin(dataPin, irqPin, keymap)` | Initialize with a custom keymap | +| `available()` | Returns `true` if a key is available to read | +| `read()` | Returns the next character (UTF-8 encoded) | +| `readUnicode()` | Returns the next character as Unicode | +| `readScanCode()` | Returns the raw PS/2 scan code | +| `clear()` | Clears the keyboard buffer | + +### Special Key Constants + +```cpp +PS2_ENTER // Enter key +PS2_TAB // Tab key +PS2_ESC // Escape key +PS2_BACKSPACE // Backspace key +PS2_DELETE // Delete key +PS2_INSERT // Insert key +PS2_HOME // Home key +PS2_END // End key +PS2_PAGEUP // Page Up key +PS2_PAGEDOWN // Page Down key +PS2_UPARROW // Up arrow +PS2_DOWNARROW // Down arrow +PS2_LEFTARROW // Left arrow +PS2_RIGHTARROW // Right arrow +PS2_F1 - PS2_F12 // Function keys +``` + +## Platform-Specific Configuration + +### ESP32 + +```ini +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino +monitor_speed = 115200 +lib_deps = + https://github.com/lahirunirmalx/PS2Keyboard +``` + +### Arduino Uno + +```ini +[env:uno] +platform = atmelavr +board = uno +framework = arduino +monitor_speed = 115200 +lib_deps = + https://github.com/lahirunirmalx/PS2Keyboard +``` + +## Examples + +- **Simple_Test**: Basic keyboard input example +- **TypeToDisplay**: Display keyboard input on an LCD + +## Version History + +- **v3.0.0** (January 2026) + - ESP32 and ESP8266 platform support + - Improved interrupt handling + - Caps Lock, Num Lock, Scroll Lock LED support + - Code cleanup and optimization + +- **v2.4** (March 2013) + - Teensy 3.0, Arduino Due, Leonardo support + +- **v2.0** (June 2010) + - Buffering, shift key support, indexed lookups + +## Credits + +- Original library by [PJRC](http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html) +- Christian Weichel - Original author +- Paul Stoffregen - Major rewrite +- L. Abraham Smith - Arduino 13 modifications +- Cuningan - Flexible pin assignment +- Lahiru - ESP32/ESP8266 support and maintenance + +## License + +This library is licensed under the [GNU Lesser General Public License v2.1](https://www.gnu.org/licenses/lgpl-2.1.html). + +## Contributing + +Contributions are welcome! Please open an issue or submit a pull request. + +## Support + +- [GitHub Issues](https://github.com/lahirunirmalx/PS2Keyboard/issues) +- [Arduino Forum](https://forum.arduino.cc) +- [ESP32 Forum](https://www.esp32.com) diff --git a/examples/International/International.ino b/examples/International/International.ino deleted file mode 100644 index 48fba5f..0000000 --- a/examples/International/International.ino +++ /dev/null @@ -1,34 +0,0 @@ -/* PS2Keyboard library, International Keyboard Layout Example - http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html - - keyboard.begin() accepts an optional 3rd parameter to - configure the PS2 keyboard layout. Uncomment the line for - your keyboard. If it doesn't exist, you can create it in - PS2Keyboard.cpp and email paul@pjrc.com to have it included - in future versions of this library. -*/ - -#include - -const int DataPin = 8; -const int IRQpin = 5; - -PS2Keyboard keyboard; - -void setup() { - //keyboard.begin(DataPin, IRQpin, PS2Keymap_US); - keyboard.begin(DataPin, IRQpin, PS2Keymap_German); - //keyboard.begin(DataPin, IRQpin, PS2Keymap_French); - //keyboard.begin(DataPin, IRQpin, PS2Keymap_Spanish); - //keyboard.begin(DataPin, IRQpin, PS2Keymap_Italian); - //keyboard.begin(DataPin, IRQpin, PS2Keymap_UK); - Serial.begin(9600); - Serial.println("International Keyboard Test:"); -} - -void loop() { - if (keyboard.available()) { - char c = keyboard.read(); - Serial.print(c); - } -} diff --git a/examples/Simple_Test/Simple_Test.ino b/examples/Simple_Test/Simple_Test.ino index bd28b4b..2d8db4f 100644 --- a/examples/Simple_Test/Simple_Test.ino +++ b/examples/Simple_Test/Simple_Test.ino @@ -1,42 +1,38 @@ -/* PS2Keyboard library example +/* + PS2Keyboard Library - Simple Test Example - PS2Keyboard now requries both pins specified for begin() - - keyboard.begin(data_pin, irq_pin); - - Valid irq pins: - Arduino Uno: 2, 3 - Arduino Due: All pins, except 13 (LED) - Arduino Mega: 2, 3, 18, 19, 20, 21 - Teensy 3.0: All pins, except 13 (LED) - Teensy 2.0: 5, 6, 7, 8 - Teensy 1.0: 0, 1, 2, 3, 4, 6, 7, 16 - Teensy++ 2.0: 0, 1, 2, 3, 18, 19, 36, 37 - Teensy++ 1.0: 0, 1, 2, 3, 18, 19, 36, 37 - Sanguino: 2, 10, 11 - - for more information you can read the original wiki in arduino.cc - at http://www.arduino.cc/playground/Main/PS2Keyboard - or http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html + This example demonstrates basic PS/2 keyboard input. - Like the Original library and example this is under LGPL license. + Wiring: + PS/2 Data -> DataPin + PS/2 Clock -> IRQpin + PS/2 VCC -> 5V + PS/2 GND -> GND + + Valid IRQ pins by board: + Arduino Uno: 2, 3 + Arduino Mega: 2, 3, 18, 19, 20, 21 + Arduino Due: All pins (except 13) + Teensy 3.x/4.x: All digital pins + ESP32/ESP8266: All GPIO pins + + More info: https://github.com/lahirunirmalx/PS2Keyboard - Modified by Cuninganreset@gmail.com on 2010-03-22 - Modified by Paul Stoffregen June 2010 + License: LGPL v2.1 */ - + #include const int DataPin = 8; -const int IRQpin = 5; +const int IRQpin = 5; PS2Keyboard keyboard; void setup() { delay(1000); keyboard.begin(DataPin, IRQpin); - Serial.begin(9600); - Serial.println("Keyboard Test:"); + Serial.begin(115200); + Serial.println("PS/2 Keyboard Test - Type to begin:"); } void loop() { diff --git a/examples/TypeToDisplay/TypeToDisplay.ino b/examples/TypeToDisplay/TypeToDisplay.ino index 2b28f15..3dceb10 100644 --- a/examples/TypeToDisplay/TypeToDisplay.ino +++ b/examples/TypeToDisplay/TypeToDisplay.ino @@ -1,33 +1,23 @@ -/* TypeToDisplay - PS2Keyboard keystrokes show on a standard LCD Display - - Lcd support added 18/2/2018 D.R.Patterson - lcd character set: +/* + PS2Keyboard Library - Type To Display Example + + Display PS/2 keyboard keystrokes on a standard LCD display. + Tested on Arduino Mega with a Keypad Shield. + + LCD character set reference: http://forum.arduino.cc/index.php?topic=19002.0 - Tested on a mega with a Keypad Shield for Arduino - - PS2Keyboard now requries both pins specified for begin() - keyboard.begin(data_pin, irq_pin); - - Valid irq pins: - Arduino Uno: 2, 3 - Arduino Due: All pins, except 13 (LED) - Arduino Mega: 2, 3, 18, 19, 20, 21 - Teensy 2.0: All pins, except 13 (LED) - Teensy 2.0: 5, 6, 7, 8 - Teensy 1.0: 0, 1, 2, 3, 4, 6, 7, 16 - Teensy++ 2.0: 0, 1, 2, 3, 18, 19, 36, 37 - Teensy++ 1.0: 0, 1, 2, 3, 18, 19, 36, 37 - Sanguino: 2, 10, 11 - - for more information you can read the original wiki in arduino.cc - at http://www.arduino.cc/playground/Main/PS2Keyboard - or http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html - - Like the Original library and example this is under LGPL license. - - Modified by Cuninganreset@gmail.com on 2010-03-22 - Modified by Paul Stoffregen June 2010 + Wiring: + PS/2 Data -> DataPin (19) + PS/2 Clock -> IRQpin (18) + PS/2 VCC -> 5V + PS/2 GND -> GND + + More info: https://github.com/lahirunirmalx/PS2Keyboard + + License: LGPL v2.1 + + Original LCD support by D.R.Patterson (2018) */ #include diff --git a/keywords.txt b/keywords.txt index bd2c18a..b374c6e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -7,20 +7,48 @@ ####################################### PS2Keyboard KEYWORD1 +PS2Keymap_t KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### +begin KEYWORD2 +available KEYWORD2 +read KEYWORD2 +readUnicode KEYWORD2 +readScanCode KEYWORD2 +clear KEYWORD2 + ####################################### # Constants (LITERAL1) ####################################### -PS2_KC_BREAK LITERAL1 -PS2_KC_ENTER LITERAL1 -PS2_KC_ESC LITERAL1 -PS2_KC_KPLUS LITERAL1 -PS2_KC_KMINUS LITERAL1 -PS2_KC_KMULTI LITERAL1 -PS2_KC_NUM LITERAL1 -PS2_KC_BKSP LITERAL1 +PS2Keymap_US LITERAL1 +PS2_TAB LITERAL1 +PS2_ENTER LITERAL1 +PS2_BACKSPACE LITERAL1 +PS2_ESC LITERAL1 +PS2_INSERT LITERAL1 +PS2_DELETE LITERAL1 +PS2_HOME LITERAL1 +PS2_END LITERAL1 +PS2_PAGEUP LITERAL1 +PS2_PAGEDOWN LITERAL1 +PS2_UPARROW LITERAL1 +PS2_LEFTARROW LITERAL1 +PS2_DOWNARROW LITERAL1 +PS2_RIGHTARROW LITERAL1 +PS2_F1 LITERAL1 +PS2_F2 LITERAL1 +PS2_F3 LITERAL1 +PS2_F4 LITERAL1 +PS2_F5 LITERAL1 +PS2_F6 LITERAL1 +PS2_F7 LITERAL1 +PS2_F8 LITERAL1 +PS2_F9 LITERAL1 +PS2_F10 LITERAL1 +PS2_F11 LITERAL1 +PS2_F12 LITERAL1 +PS2_SCROLL LITERAL1 diff --git a/library.json b/library.json index 77cc9c1..09604e5 100644 --- a/library.json +++ b/library.json @@ -1,14 +1,12 @@ { "name": "PS2Keyboard", - "keywords": "keyboard, emulation", - "description": "PS2Keyboard (PS/2) allows you to use a keyboard for user input", - "authors": - [ + "keywords": "keyboard, ps2, input, esp32, esp8266", + "description": "PS2Keyboard library allows you to use a PS/2 keyboard for user input. Supports Arduino, Teensy, ESP32, and ESP8266.", + "authors": [ { "name": "Paul Stoffregen", "email": "paul@pjrc.com", - "url": "http://www.pjrc.com", - "maintainer": true + "url": "http://www.pjrc.com" }, { "name": "Christian Weichel", @@ -21,22 +19,29 @@ { "name": "Cuningan", "email": "cuninganreset@gmail.com" + }, + { + "name": "Lahiru", + "email": "lahirunirmalx@gmail.com", + "maintainer": true } ], - "repository": - { + "repository": { "type": "git", - "url": "https://github.com/PaulStoffregen/PS2Keyboard.git" + "url": "https://github.com/lahirunirmalx/PS2Keyboard.git" }, - "version": "2.4", - "homepage": "http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html", + "version": "3.0.0", + "license": "LGPL-2.1", + "homepage": "https://github.com/lahirunirmalx/PS2Keyboard", "frameworks": "arduino", - "platforms": - [ + "platforms": [ "atmelavr", - "teensy" + "atmelsam", + "teensy", + "espressif32", + "espressif8266" ], "examples": [ - "examples/*/*.pde" + "examples/*/*.ino" ] } diff --git a/library.properties b/library.properties index 340d0ba..9ea5063 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=PS2Keyboard -version=2.4 -author=Christian Weichel, Paul Stoffregen, L. Abraham Smith, Cuningan -maintainer=Paul Stoffregen -sentence=Use a PS/2 Keyboard for input -paragraph= +version=3.0.0 +author=Christian Weichel, Paul Stoffregen, L. Abraham Smith, Cuningan, Lahiru +maintainer=Lahiru +sentence=Use a PS/2 keyboard for user input. +paragraph=Supports Arduino, Teensy, ESP32, ESP8266 and other boards. Features include Caps Lock, Num Lock, and Scroll Lock LED support. category=Signal Input/Output -url=https://github.com/PaulStoffregen/PS2Keyboard +url=https://github.com/lahirunirmalx/PS2Keyboard architectures=* - +includes=PS2Keyboard.h