diff --git a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyAdvanced.cpp b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyAdvanced.cpp new file mode 100644 index 0000000..efca0c1 --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyAdvanced.cpp @@ -0,0 +1,1016 @@ +/* Version V1.0.9 + PS2KeyAdvanced.cpp - PS2KeyAdvanced library + Copyright (c) 2007 Free Software Foundation. All right reserved. + Written by Paul Carpenter, PC Services + Created September 2014 + Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management + January 2020 Fix typos, correct keyboard reset status improve library.properties + and additional platform handling and some documentation + March 2020 Add SAMD1 as recognised support as has been tested by user + Improve different architecture handling + November 2020 Add support for STM32 from user Hiabuto-de + Tested on STM32Duino-Framework and PlatformIO on STM32F103C8T6 and an IBM Model M + July 2021 Add workaround for ESP32 issue with Silicon (hardware) from user submissions + + IMPORTANT WARNING + + If using a DUE or similar board with 3V3 I/O you MUST put a level translator + like a Texas Instruments TXS0102 or FET circuit as the signals are + Bi-directional (signals transmitted from both ends on same wire). + + Failure to do so may damage your Arduino Due or similar board. + + Test History + September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 + January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board + Manager V1.6.6 + + + Assumption - Only ONE keyboard added to one Arduino + - No stream support + + This is for a LATIN style keyboard using Scan code set 2. See various + websites on what different scan code sets use. Scan Code Set 2 is the + default scan code set for PS2 keyboards on power up. + + Fully featured PS2 keyboard library to provide + All keys as a keycode (A-Z and 0-9 as ASCII equivalents) + All function and movement keys supported even multi-lingual + Parity checking of data sent/received on receive request keyboard resend + Resends data when needed handles keyboard protocol for RESEND and ECHO + Functions for get and set of + Scancode set in use READ only + LED and LOCK control + ReadID + Reset keyboard + Send ECHO + Handles NUM, _CAPS and SCROLL lock keys to LEDs + Handles NUM/SCROLL internally + + Returns an uint16_t containing + Make/Break status + CAPS status + SHIFT, CTRL, ALT, ALT GR, GUI keys + Flag for function key not a displayable/printable character + 8 bit key code + + Code Ranges(bottom byte of uint16_t) see PS2KeyAdvanced.h for details + 0 invalid/error + 1-1F Functions (_CAPS, _SHIFT, _ALT, Enter, DEL... ) + 1A-1F Functions with ASCII control code + (DEL, BS, TAB, ESC, ENTER, SPACE) + 20-60 Printable characters noting + 0-9 = 0x30 to 0x39 as ASCII + A to Z = 0x41 to 0x5A as upper case ASCII type codes + 8B Extra European key + 61-A0 Function keys and other special keys (plus F2 and F1 less 8B) + 61-78 F1 to F24 + 79-8A Multimedia + 8C-8E ACPI power + 91-A0 and F2 and F1 - Special multilingual + A8-FF Keyboard communications commands (note F2 and F1 are special + codes for special multi-lingual keyboards) + + By using these ranges it is possible to perform detection of any key and do + easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code. + + Top Byte is 8 bits denoting as follows with defines for bit code + + Define name bit description + PS2_BREAK 15 1 = Break key code + (MSB) 0 = Make Key code + PS2_SHIFT 14 1 = Shift key pressed as well (either side) + 0 = NO shift key + PS2_CTRL 13 1 = Ctrl key pressed as well (either side) + 0 = NO Ctrl key + PS2_CAPS 12 1 = Caps Lock ON + 0 = Caps lock OFF + PS2_ALT 11 1 = Left Alt key pressed as well + 0 = NO Left Alt key + PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well + 0 = NO Right Alt key + PS2_GUI 9 1 = GUI key pressed as well (either) + 0 = NO GUI key + PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter) + 0 = standard character key + + Error Codes + Most functions return 0 or 0xFFFF as error, other codes to note and + handle appropriately value in bottom byte + 0xAA keyboard has reset and passed power up tests + will happen if keyboard plugged in after code start + 0xFC Keyboard General error or power up fail + + It is responsibility of your programme to deal with converting special cases + like <_CTRL>+ sends a special code to something else. A better method + is to use PS2KeyMap library and add your own table to that library. If you + wish to do that make a NEW library called SOMETHING different NOT a variant + or revision of this one, as you are changing base functionality + + See PS2KeyCode.h for codes from the keyboard this library uses to decode. + (may disappear in updates do not rely on this file or definitions) + + See PS2KeyAvanced.h for returned definitions of Keys and accessible + definitions + + See PS2KeyMap.h for tables currently supported + + To get the key as ASCII/UTF-8 single byte character conversion requires use + of PS2KeyMap library AS WELL. + + 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 +// Internal headers for library defines/codes/etc +#include "PS2KeyAdvanced.h" +#include "PS2KeyCode.h" +#include "PS2KeyTable.h" + + +// Private function declarations +void send_bit( void ); +void send_now( uint8_t ); +int16_t send_next( void ); +void ps2_reset( void ); +uint8_t decode_key( uint8_t ); +void pininput( uint8_t ); +void set_lock( ); + +/* Constant control functions to flags array + in translated key code value order */ +#if defined( PS2_REQUIRES_PROGMEM ) +const uint8_t PROGMEM control_flags[] = { +#else +const uint8_t control_flags[] = { +#endif + _SHIFT, _SHIFT, _CTRL, _CTRL, + _ALT, _ALT_GR, _GUI, _GUI + }; + +// Private Variables +volatile uint8_t _ps2mode; /* _ps2mode contains + _PS2_BUSY bit 7 = busy until all expected bytes RX/TX + _TX_MODE bit 6 = direction 1 = TX, 0 = RX (default) + _BREAK_KEY bit 5 = break code detected + _WAIT_RESPONSE bit 4 = expecting data response + _E0_MODE bit 3 = in E0 mode + _E1_MODE bit 2 = in E1 mode + _LAST_VALID bit 1 = last sent valid in case we receive resend + and not sent anything */ + +/* volatile RX buffers and variables accessed via interrupt functions */ +volatile uint16_t _rx_buffer[ _RX_BUFFER_SIZE ]; // buffer for data from keyboard +volatile uint8_t _head; // _head = last byte written +uint8_t _tail; // _tail = last byte read (not modified in IRQ ever) +volatile int8_t _bytes_expected; +volatile uint8_t _bitcount; // Main state variable and bit count for interrupts +volatile uint8_t _shiftdata; +volatile uint8_t _parity; + +/* TX variables */ +volatile uint8_t _tx_buff[ _TX_BUFFER_SIZE ]; // buffer for keyboard commands +volatile uint8_t _tx_head; // buffer write pointer +volatile uint8_t _tx_tail; // buffer read pointer +volatile uint8_t _last_sent; // last byte if resend requested +volatile uint8_t _now_send; // immediate byte to send +volatile uint8_t _response_count; // bytes expected in reply to next TX +volatile uint8_t _tx_ready; // TX status for type of send contains + /* _HANDSHAKE 0x80 = handshaking command (ECHO/RESEND) + _COMMAND 0x01 = other command processing */ + +/* Output key buffering */ +uint16_t _key_buffer[ _KEY_BUFF_SIZE ]; // Output Buffer for translated keys +uint8_t _key_head; // Output buffer WR pointer +uint8_t _key_tail; // Output buffer RD pointer +uint8_t _mode = 0; // Mode for output buffer contains + /* _NO_REPEATS 0x80 No repeat make codes for _CTRL, _ALT, _SHIFT, _GUI + _NO_BREAKS 0x08 No break codes */ + +// Arduino settings for pins and interrupts Needed to send data +uint8_t PS2_DataPin; +uint8_t PS2_IrqPin; + +// Key decoding variables +uint8_t PS2_led_lock = 0; // LED and Lock status +uint8_t PS2_lockstate[ 4 ]; // Save if had break on key for locks +uint8_t PS2_keystatus; // current CAPS etc status for top byte + + +/*------------------ Code starts here -------------------------*/ + +/* The ISR for the external interrupt + To receive 11 bits - start 8 data, ODD parity, stop + To send data calls send_bit( ) + Interrupt every falling incoming clock edge from keyboard */ +void ps2interrupt( void ) +{ +// Workaround for ESP32 SILICON error see extra/Porting.md +#ifdef PS2_ONLY_CHANGE_IRQ +if( digitalRead( PS2_IrqPin ) ) + return; +#endif +if( _ps2mode & _TX_MODE ) + send_bit( ); +else + { + static uint32_t prev_ms = 0; + uint32_t now_ms; + uint8_t val, ret; + + val = digitalRead( PS2_DataPin ); + /* timeout catch for glitches reset everything */ + now_ms = millis( ); + if( now_ms - prev_ms > 250 ) + { + _bitcount = 0; + _shiftdata = 0; + } + prev_ms = now_ms; + _bitcount++; // Now point to next bit + switch( _bitcount ) + { + case 1: // Start bit + _parity = 0; + _ps2mode |= _PS2_BUSY; // set busy + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: // Data bits + _parity += val; // another one received ? + _shiftdata >>= 1; // right _SHIFT one place for next bit + _shiftdata |= ( val ) ? 0x80 : 0; // or in MSbit + break; + case 10: // Parity check + _parity &= 1; // Get LSB if 1 = odd number of 1's so parity bit should be 0 + if( _parity == val ) // Both same parity error + _parity = 0xFD; // To ensure at next bit count clear and discard + break; + case 11: // Stop bit lots of spare time now + if( _parity >= 0xFD ) // had parity error + { + send_now( PS2_KC_RESEND ); // request resend + _tx_ready |= _HANDSHAKE; + } + else // Good so save byte in _rx_buffer + { + // Check _SHIFTed data for commands and action + ret = decode_key( _shiftdata ); + if( ret & 0x2 ) // decrement expected bytes + _bytes_expected--; + if( _bytes_expected <= 0 || ret & 4 ) // Save value ?? + { + val = _head + 1; + if( val >= _RX_BUFFER_SIZE ) + val = 0; + if( val != _tail ) + { + // get last byte to save + _rx_buffer[ val ] = uint16_t( _shiftdata ); + // save extra details + _rx_buffer[ val ] |= uint16_t( _ps2mode ) << 8; + _head = val; + } + } + if( ret & 0x10 ) // Special command to send (ECHO/RESEND) + { + send_now( _now_send ); + _tx_ready |= _HANDSHAKE; + } + else + if( _bytes_expected <= 0 ) // Receive data finished + { + // Set mode and status for next receive byte + _ps2mode &= ~( _E0_MODE + _E1_MODE + _WAIT_RESPONSE + _BREAK_KEY ); + _bytes_expected = 0; + _ps2mode &= ~_PS2_BUSY; + send_next( ); // Check for more to send + } + } + _bitcount = 0; // end of byte + break; + default: // in case of weird error and end of byte reception re-sync + _bitcount = 0; + } + } +} + + +/* Decode value received to check for errors commands and responses + NOT keycode translate yet + returns bit Or'ing + 0x10 send command in _now_send (after any saves and decrements) + 0x08 error abort reception and reset status and queues + 0x04 save value ( complete after translation ) + 0x02 decrement count of bytes to expected + + Codes like EE, AA and FC ( Echo, BAT pass and fail) treated as valid codes + return code 6 +*/ +uint8_t decode_key( uint8_t value ) +{ +uint8_t state; + +state = 6; // default state save and decrement + +// Anything but resend received clear valid value to resend +if( value != PS2_KC_RESEND ) + _ps2mode &= ~( _LAST_VALID ); + +// First check not a valid response code from a host command +if( _ps2mode & _WAIT_RESPONSE ) + if( value < 0xF0 ) + return state; // Save response and decrement + +// E1 Pause mode special case just decrement +if( _ps2mode & _E1_MODE ) + return 2; + +switch( value ) + { + case 0: // Buffer overrun Errors Reset modes and buffers + case PS2_KC_OVERRUN: + ps2_reset( ); + state = 0xC; + break; + case PS2_KC_RESEND: // Resend last byte if we have sent something + if( ( _ps2mode & _LAST_VALID ) ) + { + _now_send = _last_sent; + state = 0x10; + } + else + state = 0; + break; + case PS2_KC_ERROR: // General error pass up but stop any sending or receiving + _bytes_expected = 0; + _ps2mode = 0; + _tx_ready = 0; + state = 0xE; + break; + case PS2_KC_KEYBREAK: // break Code - wait the final key byte + _bytes_expected = 1; + _ps2mode |= _BREAK_KEY; + state = 0; + break; + case PS2_KC_ECHO: // Echo if we did not originate echo back + state = 4; // always save + if( _ps2mode & _LAST_VALID && _last_sent != PS2_KC_ECHO ) + { + _now_send = PS2_KC_ECHO; + state |= 0x10; // send _command on exit + } + break; + case PS2_KC_BAT: // BAT pass + _bytes_expected = 0; // reset as if in middle of something lost now + state = 4; + break; + case PS2_KC_EXTEND1: // Major extend code (PAUSE key only) + if( !( _ps2mode & _E1_MODE ) ) // First E1 only + { + _bytes_expected = 7; // seven more bytes + _ps2mode |= _E1_MODE; + _ps2mode &= ~_BREAK_KEY; // Always a make + } + state = 0; + break; + case PS2_KC_EXTEND: // Two byte Extend code + _bytes_expected = 1; // one more byte at least to wait for + _ps2mode |= _E0_MODE; + state = 0; + break; + } +return state; +} + + +/* Send data to keyboard + Data pin direction should already be changed + Start bit would be already set so each clock setup for next clock + parity and _bitcount should be 0 already and busy should be set + + Start bit setting is due to bug in attachinterrupt not clearing pending interrupts + Also no clear pending interrupt function */ +void send_bit( void ) +{ +uint8_t val; + +_bitcount++; // Now point to next bit +switch( _bitcount ) + { + case 1: +#if defined( PS2_CLEAR_PENDING_IRQ ) + // Start bit due to Arduino bug + digitalWrite( PS2_DataPin, LOW ); + break; +#endif + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + // Data bits + val = _shiftdata & 0x01; // get LSB + digitalWrite( PS2_DataPin, val ); // send start bit + _parity += val; // another one received ? + _shiftdata >>= 1; // right _SHIFT one place for next bit + break; + case 10: + // Parity - Send LSB if 1 = odd number of 1's so parity should be 0 + digitalWrite( PS2_DataPin, ( ~_parity & 1 ) ); + break; + case 11: // Stop bit write change to input pull up for high stop bit + pininput( PS2_DataPin ); + break; + case 12: // Acknowledge bit low we cannot do anything if high instead of low + if( !( _now_send == PS2_KC_ECHO || _now_send == PS2_KC_RESEND ) ) + { + _last_sent = _now_send; // save in case of resend request + _ps2mode |= _LAST_VALID; + } + // clear modes to receive again + _ps2mode &= ~_TX_MODE; + if( _tx_ready & _HANDSHAKE ) // If _HANDSHAKE done + _tx_ready &= ~_HANDSHAKE; + else // else we finished a command + _tx_ready &= ~_COMMAND; + if( !( _ps2mode & _WAIT_RESPONSE ) ) // if not wait response + send_next( ); // check anything else to queue up + _bitcount = 0; // end of byte + break; + default: // in case of weird error and end of byte reception re-sync + _bitcount = 0; + } +} + + +/* Takes a byte sets up variables and starts the data sending processes + Starts the actual byte transmission + calling code must make sure line is idle and able to send + Whilst this function adds long delays the process of the delays + will STOP the interrupt source (keyboard) externally when clock held low + _tx_ready contains 2 flags checked in this order + _HANDSHAKE command sent as part of receiving e.g. ECHO, RESEND + _COMMAND other commands not part of receiving + Main difference _bytes_expected is NOT altered in _HANDSHAKE mode + in command mode we update _bytes_expected with number of response bytes +*/ +void send_now( uint8_t command ) +{ +_shiftdata = command; +_now_send = command; // copy for later to save in last sent +#if defined( PS2_CLEAR_PENDING_IRQ ) +_bitcount = 0; // AVR/SAM ignore extra interrupt +#else +_bitcount = 1; // Normal processors +#endif +_parity = 0; +_ps2mode |= _TX_MODE + _PS2_BUSY; + +// Only do this if sending a command not from Handshaking +if( !( _tx_ready & _HANDSHAKE ) && ( _tx_ready & _COMMAND ) ) + { + _bytes_expected = _response_count; // How many bytes command will generate + _ps2mode |= _WAIT_RESPONSE; + } + +// STOP interrupt handler +// Setting pin output low will cause interrupt before ready +detachInterrupt( digitalPinToInterrupt( PS2_IrqPin ) ); +// set pins to outputs and high +digitalWrite( PS2_DataPin, HIGH ); +pinMode( PS2_DataPin, OUTPUT ); +digitalWrite( PS2_IrqPin, HIGH ); +pinMode( PS2_IrqPin, OUTPUT ); +// Essential for PS2 spec compliance +delayMicroseconds( 10 ); +// set Clock LOW +digitalWrite( PS2_IrqPin, LOW ); +// Essential for PS2 spec compliance +// set clock low for 60us +delayMicroseconds( 60 ); +// Set data low - Start bit +digitalWrite( PS2_DataPin, LOW ); +// set clock to input_pullup data stays output while writing to keyboard +pininput( PS2_IrqPin ); +// Restart interrupt handler +attachInterrupt( digitalPinToInterrupt( PS2_IrqPin ), ps2interrupt, FALLING ); +// wait clock interrupt to send data +} + + +/* Send next byte/command from TX queue and start sending + Must be ready to send and idle + Assumes commands consist of 1 or more bytes and wait for response then may or + not be followed by further bytes to send with or without response + Checks + 1/ Buffer empty return empty buffer + 2/ Busy return busy (will be checked by interrupt routines later) + 3/ Read next byte (next byte to send) + 4/ Check if following byte(s) are command/data or response + + Returns 1 if started transmission or queued + -134 if already busy + -2 if buffer empty + + Note PS2_KEY_IGNORE is used to denote a byte(s) expected in response */ +int16_t send_next( void ) +{ +uint8_t i; +int16_t val; + +val = -1; +// Check buffer not empty +i = _tx_tail; +if( i == _tx_head ) + return -2; + +// set command bit in _tx_ready as another command to do +_tx_ready |= _COMMAND; + +// Already item waiting to be sent or sending interrupt routines will call back +if( _tx_ready & _HANDSHAKE ) + return -134; + +// if busy let interrupt catch and call us again +if( _ps2mode & _PS2_BUSY ) + return -134; + +// Following only accessed when not receiving or sending protocol bytes +// Scan for command response and expected bytes to follow +_response_count = 0; +do + { + i++; + if( i >= _TX_BUFFER_SIZE ) + i = 0; + if( val == -1 ) + val = _tx_buff[ i ]; + else + if( _tx_buff[ i ] != PS2_KEY_IGNORE ) + break; + else + _response_count++; + _tx_tail = i; + } +while( i != _tx_head ); +// Now know what to send and expect start the actual wire sending +send_now( val ); +return 1; +} + + +/* Send a byte to the TX buffer + Value in buffer of PS2_KEY_IGNORE signifies wait for response, + use one for each byte expected + + Returns -4 - if buffer full (buffer overrun not written) + Returns 1 byte written when done */ +int send_byte( uint8_t val ) +{ +uint8_t ret; + +ret = _tx_head + 1; +if( ret >= _TX_BUFFER_SIZE ) + ret = 0; +if( ret != _tx_tail ) + { + _tx_buff[ ret ] = val; + _tx_head = ret; + return 1; + } +return -4; +} + + +// initialize a data pin for input +void pininput( uint8_t pin ) +{ +#ifdef INPUT_PULLUP +pinMode( pin, INPUT_PULLUP ); +#else +digitalWrite( pin, HIGH ); +pinMode( pin, INPUT ); +#endif +} + + +void ps2_reset( void ) +{ +/* reset buffers and states */ +_tx_head = 0; +_tx_tail = 0; +_tx_ready = 0; +_response_count = 0; +_head = 0; +_tail = 0; +_bitcount = 0; +PS2_keystatus = 0; +PS2_led_lock = 0; +_ps2mode = 0; +} + + +uint8_t key_available( ) +{ +int8_t i; + +i = _head - _tail; +if( i < 0 ) + i += _RX_BUFFER_SIZE; +return uint8_t( i ); +} + + +/* Translate PS2 keyboard code sequence into our key code data + PAUSE key (_E1_MODE) is de_ALT with as special case, and + command responses not translated + + Called from read function as too long for in interrupt + + Returns 0 for no valid key or processed internally ignored or similar + 0 for empty buffer + */ +uint16_t translate( void ) +{ +uint8_t index, length, data; +uint16_t retdata; + +// get next character +// Check first something to fetch +index = _tail; +// check for empty buffer +if( index == _head ) + return 0; +index++; +if( index >= _RX_BUFFER_SIZE ) + index = 0; +_tail = index; +// Get the flags byte break modes etc in this order +data = _rx_buffer[ index ] & 0xFF; +index = ( _rx_buffer[ index ] & 0xFF00 ) >> 8; + +// Catch special case of PAUSE key +if( index & _E1_MODE ) + return PS2_KEY_PAUSE + _FUNCTION; + +// Ignore anything not actual keycode but command/response +// Return untranslated as valid +if( ( data >= PS2_KC_BAT && data != PS2_KC_LANG1 && data != PS2_KC_LANG2 ) + || ( index & _WAIT_RESPONSE ) ) + return ( uint16_t )data; + +// Gather the break of key status +if( index & _BREAK_KEY ) + PS2_keystatus |= _BREAK; +else + PS2_keystatus &= ~_BREAK; + +retdata = 0; // error code by default +// Scan appropriate table +if( index & _E0_MODE ) + { + length = sizeof( extended_key ) / sizeof( extended_key[ 0 ] ); + for( index = 0; index < length; index++ ) +#if defined( PS2_REQUIRES_PROGMEM ) + if( data == pgm_read_byte( &extended_key[ index ][ 0 ] ) ) + { + retdata = pgm_read_byte( &extended_key[ index ][ 1 ] ); +#else + if( data == extended_key[ index ][ 0 ] ) + { + retdata = extended_key[ index ][ 1 ]; +#endif + break; + } + } +else + { + length = sizeof( single_key ) / sizeof( single_key[ 0 ] ); + for( index = 0; index < length; index++ ) +#if defined( PS2_REQUIRES_PROGMEM ) + if( data == pgm_read_byte( &single_key[ index ][ 0 ] ) ) + { + retdata = pgm_read_byte( &single_key[ index ][ 1 ] ); +#else + if( data == single_key[ index ][ 0 ] ) + { + retdata = single_key[ index ][ 1 ]; +#endif + break; + } + } +// trap not found key +if( index == length ) + retdata = 0; +/* valid found values only */ +if( retdata > 0 ) + { + if( retdata <= PS2_KEY_CAPS ) + { // process lock keys need second make to turn off + if( PS2_keystatus & _BREAK ) + { + PS2_lockstate[ retdata ] = 0; // Set received a break so next make toggles LOCK status + retdata = PS2_KEY_IGNORE; // ignore key + } + else + { + if( PS2_lockstate[ retdata ] == 1 ) + retdata = PS2_KEY_IGNORE; // ignore key if make and not received break + else + { + PS2_lockstate[ retdata ] = 1; + switch( retdata ) + { + case PS2_KEY_CAPS: index = PS2_LOCK_CAPS; + // Set CAPS lock if not set before + if( PS2_keystatus & _CAPS ) + PS2_keystatus &= ~_CAPS; + else + PS2_keystatus |= _CAPS; + break; + case PS2_KEY_SCROLL: index = PS2_LOCK_SCROLL; + break; + case PS2_KEY_NUM: index = PS2_LOCK_NUM; + break; + } + // Now update PS2_led_lock status to match + if( PS2_led_lock & index ) + { + PS2_led_lock &= ~index; + PS2_keystatus |= _BREAK; // send as break + } + else + PS2_led_lock |= index; + set_lock( ); + } + } + } + else + if( retdata >= PS2_KEY_L_SHIFT && retdata <= PS2_KEY_R_GUI ) + { // Update bits for _SHIFT, _CTRL, _ALT, _ALT GR, _GUI in status +#if defined( PS2_REQUIRES_PROGMEM ) + index = pgm_read_byte( &control_flags[ retdata - PS2_KEY_L_SHIFT ] ); +#else + index = control_flags[ retdata - PS2_KEY_L_SHIFT ]; +#endif + if( PS2_keystatus & _BREAK ) + PS2_keystatus &= ~index; + else + // if already set ignore repeats if flag set + if( ( PS2_keystatus & index ) && ( _mode & _NO_REPEATS ) ) + retdata = PS2_KEY_IGNORE; // ignore repeat _SHIFT, _CTRL, _ALT, _GUI + else + PS2_keystatus |= index; + } + else + // Numeric keypad ONLY works in numlock state or when _SHIFT status + if( retdata >= PS2_KEY_KP0 && retdata <= PS2_KEY_KP_DOT ) + if( !( PS2_led_lock & PS2_LOCK_NUM ) || ( PS2_keystatus & _SHIFT ) ) +#if defined( PS2_REQUIRES_PROGMEM ) + retdata = pgm_read_byte( &scroll_remap[ retdata - PS2_KEY_KP0 ] ); +#else + retdata = scroll_remap[ retdata - PS2_KEY_KP0 ]; +#endif + // Sort break code handling or ignore for all having processed the _SHIFT etc status + if( ( PS2_keystatus & _BREAK ) && ( _mode & _NO_BREAKS ) ) + return ( uint16_t )PS2_KEY_IGNORE; + // Assign Function keys _mode + if( ( retdata <= PS2_KEY_SPACE || retdata >= PS2_KEY_F1 ) && retdata != PS2_KEY_EUROPE2 ) + PS2_keystatus |= _FUNCTION; + else + PS2_keystatus &= ~_FUNCTION; + } +return ( retdata | ( (uint16_t)PS2_keystatus << 8 ) ); +} + + +/* Build command to send lock status + Assumes data is within range */ +void set_lock( ) +{ +send_byte( PS2_KC_LOCK ); // send command +send_byte( PS2_KEY_IGNORE ); // wait ACK +send_byte( PS2_led_lock ); // send data from internal variable +if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait ACK + send_next( ); // if idle start transmission +} + + +/* Send echo command to keyboard + returned data in keyboard buffer read as keys */ +void PS2KeyAdvanced::echo( void ) +{ +send_byte( PS2_KC_ECHO ); // send command +if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data PS2_KC_ECHO + send_next( ); // if idle start transmission +} + + +/* Get the ID used in keyboard + returned data in keyboard buffer read as keys */ +void PS2KeyAdvanced::readID( void ) +{ +send_byte( PS2_KC_READID ); // send command +send_byte( PS2_KEY_IGNORE ); // wait ACK +send_byte( PS2_KEY_IGNORE ); // wait data +if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data + send_next( ); // if idle start transmission +} + + +/* Get the current Scancode Set used in keyboard + returned data in keyboard buffer read as keys */ +void PS2KeyAdvanced::getScanCodeSet( void ) +{ +send_byte( PS2_KC_SCANCODE ); // send command +send_byte( PS2_KEY_IGNORE ); // wait ACK +send_byte( 0 ); // send data 0 = read +send_byte( PS2_KEY_IGNORE ); // wait ACK +if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data + send_next( ); // if idle start transmission +} + + +/* Returns the current status of Locks */ +uint8_t PS2KeyAdvanced::getLock( ) +{ +return( PS2_led_lock ); +} + + +/* Sets the current status of Locks and LEDs */ +void PS2KeyAdvanced::setLock( uint8_t code ) +{ +code &= 0xF; // To allow for rare keyboards with extra LED +PS2_led_lock = code; // update our lock copy +PS2_keystatus &= ~_CAPS; // Update copy of _CAPS lock as well +PS2_keystatus |= ( code & PS2_LOCK_CAPS ) ? _CAPS : 0; +set_lock( ); +} + + +/* Set library to not send break key codes + 1 = no break codes + 0 = send break codes */ +void PS2KeyAdvanced::setNoBreak( uint8_t data ) +{ +_mode &= ~_NO_BREAKS; +_mode |= data ? _NO_BREAKS : 0; +} + + /* Set library to not repeat make codes for _CTRL, _ALT, _GUI, _SHIFT + 1 = no repeat codes + 0 = send repeat codes */ +void PS2KeyAdvanced::setNoRepeat( uint8_t data ) +{ +_mode &= ~_NO_REPEATS; +_mode |= data ? _NO_REPEATS : 0; +} + + +/* Resets keyboard when reset has completed + keyboard sends AA - Pass or FC for fail */ +void PS2KeyAdvanced::resetKey( ) +{ +send_byte( PS2_KC_RESET ); // send command +send_byte( PS2_KEY_IGNORE ); // wait ACK +if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data PS2_KC_BAT or PS2_KC_ERROR + send_next( ); // if idle start transmission +// LEDs and KeyStatus Reset too... to match keyboard +PS2_led_lock = 0; +PS2_keystatus = 0; +} + + +/* Send Typematic rate/delay command to keyboard + First Parameter rate is 0 - 0x1F (31) + 0 = 30 CPS + 0x1F = 2 CPS + default in keyboard is 0xB (10.9 CPS) + Second Parameter delay is 0 - 3 for 0.25s to 1s in 0.25 increments + default in keyboard is 1 = 0.5 second delay + Returned data in keyboard buffer read as keys + + Error returns 0 OK + -5 parameter error + */ +int PS2KeyAdvanced::typematic( uint8_t rate, uint8_t delay ) +{ +if( rate > 31 || delay > 3 ) + return -5; +send_byte( PS2_KC_RATE ); // send command +send_byte( PS2_KEY_IGNORE ); // wait ACK +send_byte( ( delay << 5 ) + rate ); // Send values +if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait ACK + send_next( ); // if idle start transmission +return 0; +} + + +/* Returns count of available processed key codes + + If processed key buffer (_key_buffer) buffer returns max count + else processes input key code buffer until + either input buffer empty + or output buffer full + returns actual count + + Returns 0 buffer empty + 1 to buffer size less 1 as 1 to full buffer + + As with other ring buffers here when pointers match + buffer empty so cannot actually hold buffer size values */ +uint8_t PS2KeyAdvanced::available( ) +{ +int8_t i, idx; +uint16_t data; + +// check output queue +i = _key_head - _key_tail; +if( i < 0 ) + i += _KEY_BUFF_SIZE; +while( i < ( _KEY_BUFF_SIZE - 1 ) ) // process if not full + if( key_available( ) ) // not check for more keys to process + { + data = translate( ); // get next translated key + if( data == 0 ) // unless in buffer is empty + break; + if( ( data & 0xFF ) != PS2_KEY_IGNORE + && ( data & 0xFF ) > 0 ) + { + idx = _key_head + 1; // point to next space + if( idx >= _KEY_BUFF_SIZE ) // loop to front if necessary + idx = 0; + _key_buffer[ idx ] = data; // save the data to out buffer + _key_head = idx; + i++; // update count + } + } + else + break; // exit nothing coming in +return uint8_t( i ); +} + + +/* read a decoded key from the keyboard buffer + returns 0 for empty buffer */ +uint16_t PS2KeyAdvanced::read( ) +{ +uint16_t result; +uint8_t idx; + +if( ( result = available( ) ) ) + { + idx = _key_tail; + idx++; + if( idx >= _KEY_BUFF_SIZE ) // loop to front if necessary + idx = 0; + _key_tail = idx; + result = _key_buffer[ idx ]; + } +return result; +} + + +PS2KeyAdvanced::PS2KeyAdvanced( ) +{ +// nothing to do here, begin( ) does it all +} + + +/* instantiate class for keyboard */ +void PS2KeyAdvanced::begin( uint8_t data_pin, uint8_t irq_pin ) +{ +/* PS2 variables reset */ +ps2_reset( ); + +PS2_DataPin = data_pin; +PS2_IrqPin = irq_pin; + +// initialize the pins +pininput( PS2_IrqPin ); /* Setup Clock pin */ +pininput( PS2_DataPin ); /* Setup Data pin */ + +// Start interrupt handler +attachInterrupt( digitalPinToInterrupt( irq_pin ), ps2interrupt, FALLING ); +} diff --git a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyAdvanced.h b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyAdvanced.h new file mode 100644 index 0000000..b89e4aa --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyAdvanced.h @@ -0,0 +1,440 @@ +/* Version V1.0.9 + PS2KeyAdvanced.h - PS2KeyAdvanced library + Copyright (c) 2007 Free Software Foundation. All right reserved. + Written by Paul Carpenter, PC Services + Created September 2014 + Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management + January 2020 Fix typos, correct keyboard reset status improve library.properties + and additional platform handling and some documentation + March 2020 Add SAMD1 as recognised support as has been tested by user + Improve different architecture handling + November 2020 Add support for STM32 from user Hiabuto-de + Tested on STM32Duino-Framework and PlatformIO on STM32F103C8T6 and an IBM Model M + July 2021 Add workaround for ESP32 issue with Silicon (hardware) from user submissions + + IMPORTANT WARNING + + If using a DUE or similar board with 3V3 I/O you MUST put a level translator + like a Texas Instruments TXS0102 or FET circuit as the signals are + Bi-directional (signals transmitted from both ends on same wire). + + Failure to do so may damage your Arduino Due or similar board. + + Test History + September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 + January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board + Manager V1.6.6 + + ONLY use defines in this file others may disappear on updates. + + This is for a LATIN style keyboard using Scan code set 2. See various + websites on what different scan code sets use. Scan Code Set 2 is the + default scan code set for PS2 keyboards on power up. + + Will support most keyboards even ones with multimedia keys or even 24 function keys. + + Fully featured PS2 keyboard library to provide + All function and movement keys supported even multi-lingual + Parity checking of data sent/received on receive request keyboard resend + Resends data when needed handles keyboard protocol for RESEND and ECHO + Functions for get and set of + Scancode set in use READ only + LED and LOCK control + ReadID + Reset keyboard + Send ECHO + Ignore Break codes for keys + Ignore typematic repeat of CTRL, SHIFT, ALT, Num, Scroll, Caps + Handles NUM, CAPS and SCROLL lock keys to LEDs + Handles NUM/SCROLL internally + + Read function Returns an UNSIGNED INT containing + Make/Break status + Caps status + Shift, CTRL, ALT, ALT GR, GUI keys + Flag for function key not a displayable/printable character + 8 bit key code + + Code Ranges (bottom byte of unsigned int) + 0 invalid/error + 1-1F Functions (Caps, Shift, ALT, Enter, DEL... ) + 1A-1F Functions with ASCII control code + (DEL, BS, TAB, ESC, ENTER, SPACE) + 20-61 Printable characters noting + 0-9 = 0x30 to 0x39 as ASCII + A to Z = 0x41 to 0x5A as upper case ASCII type codes + 8B Extra European key + 61-A0 Function keys and other special keys (plus F2 and F1) + 61-78 F1 to F24 + 79-8A Multimedia + 8B NOT included + 8C-8E ACPI power + 91-A0 and F2 and F1 - Special multilingual + A8-FF Keyboard communications commands (note F2 and F1 are special + codes for special multi-lingual keyboards) + + By using these ranges it is possible to perform detection of any key and do + easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code. + + Top Byte is 8 bits denoting as follows with defines for bit code + + Define name bit description + PS2_BREAK 15 1 = Break key code + (MSB) 0 = Make Key code + PS2_SHIFT 14 1 = Shift key pressed as well (either side) + 0 = NO shift key + PS2_CTRL 13 1 = Ctrl key pressed as well (either side) + 0 = NO Ctrl key + PS2_CAPS 12 1 = Caps Lock ON + 0 = Caps lock OFF + PS2_ALT 11 1 = Left Alt key pressed as well + 0 = NO Left Alt key + PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well + 0 = NO Right Alt key + PS2_GUI 9 1 = GUI key pressed as well (either) + 0 = NO GUI key + PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter) + 0 = standard character key + + Error Codes + Most functions return 0 or 0xFFFF as error, other codes to note and + handle appropriately + 0xAA keyboard has reset and passed power up tests + will happen if keyboard plugged in after code start + 0xFC Keyboard General error or power up fail + + It is responsibility of your programme to deal with converting special cases like + + sends a special code to something else. If you wish to do that make a + NEW library called SOMETHING different NOT a variant or revision of this one, as you + are changing base functionality + + See PS2KeyCode.h for codes from the keyboard this library uses to decode. + (may disappear in updates do not rely on that file or definitions) + + See this file for returned definitions of Keys + + Note defines starting + PS2_KC_* are internal defines for codes from the keyboard + PS2_KEY_* are the codes this library returns + PS2_* remaining defines for use in higher levels + + To get the key as ASCII/UTF-8 single byte character conversion requires use + of PS2KeyMap library AS WELL. + + 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 +*/ +#ifndef PS2KeyAdvanced_h +#define PS2KeyAdvanced_h + +// Platform specific areas +// Harvard architecture settings for PROGMEM +// Add separate for EACH architecture as easier to maintain +// AVR (includes Teensy 2.0) +#if defined( ARDUINO_ARCH_AVR ) +#define PS2_SUPPORTED 1 +#define PS2_REQUIRES_PROGMEM 1 +#define PS2_CLEAR_PENDING_IRQ 1 +#endif +// SAM (Due) +#if defined( ARDUINO_ARCH_SAM ) +#define PS2_SUPPORTED 1 +#define PS2_CLEAR_PENDING_IRQ 1 +#endif +// SAMD1 +#if defined( ARDUINO_ARCH_SAMD1 ) +#define PS2_SUPPORTED 1 +#define PS2_CLEAR_PENDING_IRQ 1 +#endif +// STM32 +#if defined( ARDUINO_ARCH_STM32 ) +#define PS2_SUPPORTED 1 +#define PS2_CLEAR_PENDING_IRQ 1 +#endif +// ESP32 +#if defined( ARDUINO_ARCH_ESP32 ) +#define PS2_SUPPORTED 1 +#define PS2_ONLY_CHANGE_IRQ 1 +#endif + +// Invalid architecture +#if !( defined( PS2_SUPPORTED ) ) +#warning Library is NOT supported on this board Use at your OWN risk +#endif + +/* Flags/bit masks for status bits in returned unsigned int value */ +#define PS2_BREAK 0x8000 +#define PS2_SHIFT 0x4000 +#define PS2_CTRL 0x2000 +#define PS2_CAPS 0x1000 +#define PS2_ALT 0x800 +#define PS2_ALT_GR 0x400 +#define PS2_GUI 0x200 +#define PS2_FUNCTION 0x100 + +/* General defines of communications codes */ +/* Command or response */ +#define PS2_KEY_RESEND 0xFE +#define PS2_KEY_ACK 0xFA +#define PS2_KEY_ECHO 0xEE +/* Responses */ +#define PS2_KEY_BAT 0xAA +// Actually buffer overrun +#define PS2_KEY_OVERRUN 0xFF +// Below is general error code +#define PS2_KEY_ERROR 0xFC + +/* Command parameters for functions */ +/* LED codes OR together */ +#define PS2_LOCK_SCROLL 0x01 +#define PS2_LOCK_NUM 0x02 +#define PS2_LOCK_CAPS 0x04 +/* Only useful for very few keyboards */ +#define PS2_LOCK_EXTRA 0x08 + +/* Returned keycode definitions */ +/* Do NOT change these codings as you will break base + functionality use PS2KeyMap for that and internationalisation */ +#define PS2_KEY_NUM 0x01 +#define PS2_KEY_SCROLL 0x02 +#define PS2_KEY_CAPS 0x03 +#define PS2_KEY_PRTSCR 0x04 +#define PS2_KEY_PAUSE 0x05 +#define PS2_KEY_L_SHIFT 0x06 +#define PS2_KEY_R_SHIFT 0x07 +#define PS2_KEY_L_CTRL 0X08 +#define PS2_KEY_R_CTRL 0X09 +#define PS2_KEY_L_ALT 0x0A +#define PS2_KEY_R_ALT 0x0B +/* Sometimes called windows key */ +#define PS2_KEY_L_GUI 0x0C +#define PS2_KEY_R_GUI 0x0D +#define PS2_KEY_MENU 0x0E +/* Break is CTRL + PAUSE generated inside keyboard */ +#define PS2_KEY_BREAK 0x0F +/* Generated by some keyboards by ALT and PRTSCR */ +#define PS2_KEY_SYSRQ 0x10 +#define PS2_KEY_HOME 0x11 +#define PS2_KEY_END 0x12 +#define PS2_KEY_PGUP 0x13 +#define PS2_KEY_PGDN 0x14 +#define PS2_KEY_L_ARROW 0x15 +#define PS2_KEY_R_ARROW 0x16 +#define PS2_KEY_UP_ARROW 0x17 +#define PS2_KEY_DN_ARROW 0x18 +#define PS2_KEY_INSERT 0x19 +#define PS2_KEY_DELETE 0x1A +#define PS2_KEY_ESC 0x1B +#define PS2_KEY_BS 0x1C +#define PS2_KEY_TAB 0x1D +#define PS2_KEY_ENTER 0x1E +#define PS2_KEY_SPACE 0x1F +#define PS2_KEY_KP0 0x20 +#define PS2_KEY_KP1 0x21 +#define PS2_KEY_KP2 0x22 +#define PS2_KEY_KP3 0x23 +#define PS2_KEY_KP4 0x24 +#define PS2_KEY_KP5 0x25 +#define PS2_KEY_KP6 0x26 +#define PS2_KEY_KP7 0x27 +#define PS2_KEY_KP8 0x28 +#define PS2_KEY_KP9 0x29 +#define PS2_KEY_KP_DOT 0x2A +#define PS2_KEY_KP_ENTER 0x2B +#define PS2_KEY_KP_PLUS 0x2C +#define PS2_KEY_KP_MINUS 0x2D +#define PS2_KEY_KP_TIMES 0x2E +#define PS2_KEY_KP_DIV 0x2F +#define PS2_KEY_0 0X30 +#define PS2_KEY_1 0X31 +#define PS2_KEY_2 0X32 +#define PS2_KEY_3 0X33 +#define PS2_KEY_4 0X34 +#define PS2_KEY_5 0X35 +#define PS2_KEY_6 0X36 +#define PS2_KEY_7 0X37 +#define PS2_KEY_8 0X38 +#define PS2_KEY_9 0X39 +#define PS2_KEY_APOS 0X3A +#define PS2_KEY_COMMA 0X3B +#define PS2_KEY_MINUS 0X3C +#define PS2_KEY_DOT 0X3D +#define PS2_KEY_DIV 0X3E +/* Some Numeric keyboards have an '=' on right keypad */ +#define PS2_KEY_KP_EQUAL 0x3F +/* Single quote or back quote */ +#define PS2_KEY_SINGLE 0X40 +#define PS2_KEY_A 0X41 +#define PS2_KEY_B 0X42 +#define PS2_KEY_C 0X43 +#define PS2_KEY_D 0X44 +#define PS2_KEY_E 0X45 +#define PS2_KEY_F 0X46 +#define PS2_KEY_G 0X47 +#define PS2_KEY_H 0X48 +#define PS2_KEY_I 0X49 +#define PS2_KEY_J 0X4A +#define PS2_KEY_K 0X4B +#define PS2_KEY_L 0X4C +#define PS2_KEY_M 0X4D +#define PS2_KEY_N 0X4E +#define PS2_KEY_O 0X4F +#define PS2_KEY_P 0X50 +#define PS2_KEY_Q 0X51 +#define PS2_KEY_R 0X52 +#define PS2_KEY_S 0X53 +#define PS2_KEY_T 0X54 +#define PS2_KEY_U 0X55 +#define PS2_KEY_V 0X56 +#define PS2_KEY_W 0X57 +#define PS2_KEY_X 0X58 +#define PS2_KEY_Y 0X59 +#define PS2_KEY_Z 0X5A +#define PS2_KEY_SEMI 0X5B +#define PS2_KEY_BACK 0X5C +#define PS2_KEY_OPEN_SQ 0X5D +#define PS2_KEY_CLOSE_SQ 0X5E +#define PS2_KEY_EQUAL 0X5F +/* Some Numeric keypads have a comma key */ +#define PS2_KEY_KP_COMMA 0x60 +#define PS2_KEY_F1 0X61 +#define PS2_KEY_F2 0X62 +#define PS2_KEY_F3 0X63 +#define PS2_KEY_F4 0X64 +#define PS2_KEY_F5 0X65 +#define PS2_KEY_F6 0X66 +#define PS2_KEY_F7 0X67 +#define PS2_KEY_F8 0X68 +#define PS2_KEY_F9 0X69 +#define PS2_KEY_F10 0X6A +#define PS2_KEY_F11 0X6B +#define PS2_KEY_F12 0X6C +#define PS2_KEY_F13 0X6D +#define PS2_KEY_F14 0X6E +#define PS2_KEY_F15 0X6F +#define PS2_KEY_F16 0X70 +#define PS2_KEY_F17 0X71 +#define PS2_KEY_F18 0X72 +#define PS2_KEY_F19 0X73 +#define PS2_KEY_F20 0X74 +#define PS2_KEY_F21 0X75 +#define PS2_KEY_F22 0X76 +#define PS2_KEY_F23 0X77 +#define PS2_KEY_F24 0X78 +#define PS2_KEY_NEXT_TR 0X79 +#define PS2_KEY_PREV_TR 0X7A +#define PS2_KEY_STOP 0X7B +#define PS2_KEY_PLAY 0X7C +#define PS2_KEY_MUTE 0X7D +#define PS2_KEY_VOL_UP 0X7E +#define PS2_KEY_VOL_DN 0X7F +#define PS2_KEY_MEDIA 0X80 +#define PS2_KEY_EMAIL 0X81 +#define PS2_KEY_CALC 0X82 +#define PS2_KEY_COMPUTER 0X83 +#define PS2_KEY_WEB_SEARCH 0X84 +#define PS2_KEY_WEB_HOME 0X85 +#define PS2_KEY_WEB_BACK 0X86 +#define PS2_KEY_WEB_FORWARD 0X87 +#define PS2_KEY_WEB_STOP 0X88 +#define PS2_KEY_WEB_REFRESH 0X89 +#define PS2_KEY_WEB_FAVOR 0X8A +#define PS2_KEY_EUROPE2 0X8B +#define PS2_KEY_POWER 0X8C +#define PS2_KEY_SLEEP 0X8D +#define PS2_KEY_WAKE 0X90 +#define PS2_KEY_INTL1 0X91 +#define PS2_KEY_INTL2 0X92 +#define PS2_KEY_INTL3 0X93 +#define PS2_KEY_INTL4 0X94 +#define PS2_KEY_INTL5 0X95 +#define PS2_KEY_LANG1 0X96 +#define PS2_KEY_LANG2 0X97 +#define PS2_KEY_LANG3 0X98 +#define PS2_KEY_LANG4 0X99 +#define PS2_KEY_LANG5 0xA0 + +/* + Purpose: Provides advanced access to PS2 keyboards + Public class definitions + + See standard error codes for error code returns + */ +class PS2KeyAdvanced { + public: + /* This constructor does basically nothing. Please call the begin(int,int) + method before using any other method of this class. */ + PS2KeyAdvanced( ); + + /* Starts the keyboard "service" by registering the external interrupt. + setting the pin modes correctly and driving those needed to high. + Sets default LOCK status (LEDs) to passed in value or default of all off + The best place to call this method is in the setup routine. */ + void begin( uint8_t, uint8_t ); + + /* Returns number of codes available or 0 for none */ + uint8_t available( ); + + /* Returns the key last read from the keyboard. + If there is no key available, 0 is returned. */ + uint16_t read( ); + + /* Returns the current status of Locks + Use Macro to mask out bits from + PS2_LOCK_NUM PS2_LOCK_CAPS PS2_LOCK_SCROLL */ + uint8_t getLock( ); + + /* Sets the current status of Locks and LEDs + Use macro defines added together from + PS2_LOCK_NUM PS2_LOCK_CAPS PS2_LOCK_SCROLL */ + void setLock( byte ); + + /* Set library to not send break key codes + 1 = no break codes + 0 = send break codes */ + void setNoBreak( uint8_t ); + + /* Set library to not repeat make codes for CTRL, ALT, GUI, SHIFT + 1 = no repeat codes + 0 = send repeat codes */ + void setNoRepeat( uint8_t ); + + /* Resets keyboard when reset has completed + keyboard sends AA - Pass or FC for fail + Read from keyboard data buffer */ + void resetKey( ); + + /* Get the current Scancode Set used in keyboard + returned data in keyboard buffer read as keys */ + void getScanCodeSet( void ); + + /* Get the current Scancode Set used in keyboard + returned data in keyboard buffer read as keys */ + void readID( void ); + + /* Send Echo command to keyboard + returned data in keyboard buffer read as keys */ + void echo( void ); + + /* Send Typematic rate/delay command to keyboard + First Parameter rate is 0 - 0x1F (31) + 0 = 30 CPS + 0x1F = 2 CPS + default in keyboard is 0xB (10.9 CPS) + Second Parameter delay is 0 - 3 for 0.25s to 1s in 0.25 increments + default in keyboard is 1 = 0.5 second delay + Returned data in keyboard buffer read as keys */ + int typematic( uint8_t , uint8_t ); +}; +#endif diff --git a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyCode.h b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyCode.h new file mode 100644 index 0000000..fbb4d44 --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyCode.h @@ -0,0 +1,276 @@ +/* Version V1.0.8 + PS2KeyCode.h - PS2KeyAdvanced library Internal actual PS2 key code sequences + Copyright (c) 2007 Free Software Foundation. All right reserved. + Written by Paul Carpenter, PC Services + Created September 2014 + Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management + Updated December 2019 - Paul Carpenter - Fix typo in code for Multimedia STOP + + PRIVATE to library + + Test History + September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 + January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board + Manager V1.6.6 + + This is for a LATIN style keyboard. Will support most keyboards even ones + with multimedia keys or even 24 function keys. + + Definitions used for key codes from a PS2 keyboard, do not use in your + code these are to be handled INTERNALLY by the library. + (may disappear in updates do not rely on this file or definitions) + + See PS2KeyAdvanced.h for codes returned from library and flag settings + + Defines are in three groups + + Special codes definition of communications bytes + + Single Byte codes returned as key codes + + Two byte Codes preceded by E0 code returned as keycodes + + 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 +*/ + +#ifndef PS2KeyCode_h +#define PS2KeyCode_h + +/* Ignore code for key code translation */ +#define PS2_KEY_IGNORE 0xBB + +// buffer sizes keyboard RX and TX, then key reading buffer +// Minimum size 8 can be larger +#define _RX_BUFFER_SIZE 8 +// Minimum size 6 can be larger +#define _TX_BUFFER_SIZE 6 +// Output Buffer of unsigned int values. Minimum size 4 can be larger +#define _KEY_BUFF_SIZE 4 + +/* private defines for library files not global */ +/* _ps2mode status flags */ +#define _PS2_BUSY 0x80 +#define _TX_MODE 0x40 +#define _BREAK_KEY 0x20 +#define _WAIT_RESPONSE 0x10 +#define _E0_MODE 0x08 +#define _E1_MODE 0x04 +#define _LAST_VALID 0x02 + +/* _tx_ready flags */ +#define _HANDSHAKE 0x80 +#define _COMMAND 0x01 + +/* Key Repeat defines */ +#define _NO_BREAKS 0x08 +#define _NO_REPEATS 0x80 + +/* PS2_keystatus byte masks (from 16 bit int masks) */ +#define _BREAK ( PS2_BREAK >> 8 ) +#define _SHIFT ( PS2_SHIFT >> 8 ) +#define _CTRL ( PS2_CTRL >> 8 ) +#define _CAPS ( PS2_CAPS >> 8 ) +#define _ALT ( PS2_ALT >> 8 ) +#define _ALT_GR ( PS2_ALT_GR >> 8 ) +#define _GUI ( PS2_GUI >> 8 ) +#define _FUNCTION ( PS2_FUNCTION >> 8 ) + +/* General defines of comms codes */ +/* Command or response */ +#define PS2_KC_RESEND 0xFE +#define PS2_KC_ACK 0xFA +#define PS2_KC_ECHO 0xEE +/* Responses */ +#define PS2_KC_BAT 0xAA +// Actually buffer overrun +#define PS2_KC_OVERRUN 0xFF +// Below is general error code +#define PS2_KC_ERROR 0xFC +#define PS2_KC_KEYBREAK 0xF0 +#define PS2_KC_EXTEND1 0xE1 +#define PS2_KC_EXTEND 0xE0 +/* Commands */ +#define PS2_KC_RESET 0xFF +#define PS2_KC_DEFAULTS 0xF6 +#define PS2_KC_DISABLE 0xF5 +#define PS2_KC_ENABLE 0xF4 +#define PS2_KC_RATE 0xF3 +#define PS2_KC_READID 0xF2 +#define PS2_KC_SCANCODE 0xF0 +#define PS2_KC_LOCK 0xED + +/* Single Byte Key Codes */ +#define PS2_KC_NUM 0x77 +#define PS2_KC_SCROLL 0x7E +#define PS2_KC_CAPS 0x58 +#define PS2_KC_L_SHIFT 0x12 +#define PS2_KC_R_SHIFT 0x59 +/* This is Left CTRL and ALT but Right version is in E0 with same code */ +#define PS2_KC_CTRL 0X14 +#define PS2_KC_ALT 0x11 +/* Generated by some keyboards by ALT and PRTSCR */ +#define PS2_KC_SYSRQ 0x84 +#define PS2_KC_ESC 0x76 +#define PS2_KC_BS 0x66 +#define PS2_KC_TAB 0x0D +#define PS2_KC_ENTER 0x5A +#define PS2_KC_SPACE 0x29 +#define PS2_KC_KP0 0x70 +#define PS2_KC_KP1 0x69 +#define PS2_KC_KP2 0x72 +#define PS2_KC_KP3 0x7A +#define PS2_KC_KP4 0x6B +#define PS2_KC_KP5 0x73 +#define PS2_KC_KP6 0x74 +#define PS2_KC_KP7 0x6C +#define PS2_KC_KP8 0x75 +#define PS2_KC_KP9 0x7D +#define PS2_KC_KP_DOT 0x71 +#define PS2_KC_KP_PLUS 0x79 +#define PS2_KC_KP_MINUS 0x7B +#define PS2_KC_KP_TIMES 0x7C +/* Some keyboards have an '=' on right keypad */ +#define PS2_KC_KP_EQUAL 0x0F +#define PS2_KC_0 0X45 +#define PS2_KC_1 0X16 +#define PS2_KC_2 0X1E +#define PS2_KC_3 0X26 +#define PS2_KC_4 0X25 +#define PS2_KC_5 0X2E +#define PS2_KC_6 0X36 +#define PS2_KC_7 0X3D +#define PS2_KC_8 0X3E +#define PS2_KC_9 0X46 +#define PS2_KC_APOS 0X52 +#define PS2_KC_COMMA 0X41 +#define PS2_KC_MINUS 0X4E +#define PS2_KC_DOT 0X49 +#define PS2_KC_DIV 0X4A +/* Single quote or back apostrophe */ +#define PS2_KC_SINGLE 0X0E +#define PS2_KC_A 0X1C +#define PS2_KC_B 0X32 +#define PS2_KC_C 0X21 +#define PS2_KC_D 0X23 +#define PS2_KC_E 0X24 +#define PS2_KC_F 0X2B +#define PS2_KC_G 0X34 +#define PS2_KC_H 0X33 +#define PS2_KC_I 0X43 +#define PS2_KC_J 0X3B +#define PS2_KC_K 0X42 +#define PS2_KC_L 0X4B +#define PS2_KC_M 0X3A +#define PS2_KC_N 0X31 +#define PS2_KC_O 0X44 +#define PS2_KC_P 0X4D +#define PS2_KC_Q 0X15 +#define PS2_KC_R 0X2D +#define PS2_KC_S 0X1B +#define PS2_KC_T 0X2C +#define PS2_KC_U 0X3C +#define PS2_KC_V 0X2A +#define PS2_KC_W 0X1D +#define PS2_KC_X 0X22 +#define PS2_KC_Y 0X35 +#define PS2_KC_Z 0X1A +#define PS2_KC_SEMI 0X4C +#define PS2_KC_BACK 0X5D +// Extra key left of Z on 102 keyboards +#define PS2_KC_EUROPE2 0x61 +#define PS2_KC_OPEN_SQ 0X54 +#define PS2_KC_CLOSE_SQ 0X5B +#define PS2_KC_EQUAL 0X55 +#define PS2_KC_F1 0X05 +#define PS2_KC_F2 0X06 +#define PS2_KC_F3 0X04 +#define PS2_KC_F4 0X0C +#define PS2_KC_F5 0X03 +#define PS2_KC_F6 0X0B +#define PS2_KC_F7 0X83 +#define PS2_KC_F8 0X0A +#define PS2_KC_F9 0X01 +#define PS2_KC_F10 0X09 +#define PS2_KC_F11 0X78 +#define PS2_KC_F12 0X07 +#define PS2_KC_F13 0X08 +#define PS2_KC_F14 0X10 +#define PS2_KC_F15 0X18 +#define PS2_KC_F16 0X20 +#define PS2_KC_F17 0X28 +#define PS2_KC_F18 0X30 +#define PS2_KC_F19 0X38 +#define PS2_KC_F20 0X40 +#define PS2_KC_F21 0X48 +#define PS2_KC_F22 0X50 +#define PS2_KC_F23 0X57 +#define PS2_KC_F24 0X5F +#define PS2_KC_KP_COMMA 0X6D +#define PS2_KC_INTL1 0X51 +#define PS2_KC_INTL2 0X13 +#define PS2_KC_INTL3 0X6A +#define PS2_KC_INTL4 0X64 +#define PS2_KC_INTL5 0X67 +#define PS2_KC_LANG1 0XF2 +#define PS2_KC_LANG2 0XF1 +#define PS2_KC_LANG3 0X63 +#define PS2_KC_LANG4 0X62 +#define PS2_KC_LANG5 0X5F + +/* Extended key codes E0 table for two byte codes */ +/* PS2_CTRL and PS2_ALT Need using in any table for the right keys */ +/* first is special case for PRTSCR not always used so ignored by decoding */ +#define PS2_KC_IGNORE 0x12 +#define PS2_KC_PRTSCR 0x7C +/* Sometimes called windows key */ +#define PS2_KC_L_GUI 0x1F +#define PS2_KC_R_GUI 0x27 +#define PS2_KC_MENU 0x2F +/* Break is CTRL + PAUSE generated inside keyboard */ +#define PS2_KC_BREAK 0x7E +#define PS2_KC_HOME 0x6C +#define PS2_KC_END 0x69 +#define PS2_KC_PGUP 0x7D +#define PS2_KC_PGDN 0x7A +#define PS2_KC_L_ARROW 0x6B +#define PS2_KC_R_ARROW 0x74 +#define PS2_KC_UP_ARROW 0x75 +#define PS2_KC_DN_ARROW 0x72 +#define PS2_KC_INSERT 0x70 +#define PS2_KC_DELETE 0x71 +#define PS2_KC_KP_ENTER 0x5A +#define PS2_KC_KP_DIV 0x4A +#define PS2_KC_NEXT_TR 0X4D +#define PS2_KC_PREV_TR 0X15 +#define PS2_KC_STOP 0X3B +#define PS2_KC_PLAY 0X34 +#define PS2_KC_MUTE 0X23 +#define PS2_KC_VOL_UP 0X32 +#define PS2_KC_VOL_DN 0X21 +#define PS2_KC_MEDIA 0X50 +#define PS2_KC_EMAIL 0X48 +#define PS2_KC_CALC 0X2B +#define PS2_KC_COMPUTER 0X40 +#define PS2_KC_WEB_SEARCH 0X10 +#define PS2_KC_WEB_HOME 0X3A +#define PS2_KC_WEB_BACK 0X38 +#define PS2_KC_WEB_FORWARD 0X30 +#define PS2_KC_WEB_STOP 0X28 +#define PS2_KC_WEB_REFRESH 0X20 +#define PS2_KC_WEB_FAVOR 0X18 +#define PS2_KC_POWER 0X37 +#define PS2_KC_SLEEP 0X3F +#define PS2_KC_WAKE 0X5E +#endif diff --git a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyTable.h b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyTable.h new file mode 100644 index 0000000..0122641 --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/PS2KeyTable.h @@ -0,0 +1,253 @@ +/* Version V1.0.8 + PS2KeyTable.h - PS2KeyAdvanced library keycode values to return values + Copyright (c) 2007 Free Software Foundation. All right reserved. + Written by Paul Carpenter, PC Services + Created September 2014 + V1.0.2 Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management + + PRIVATE to library + + Test History + September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 + January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board + Manager V1.6.6 + + Internal to library private tables + (may disappear in updates do not rely on this file or definitions) + + This is for a LATIN style keyboard. Will support most keyboards even ones + with multimedia keys or even 24 function keys. + + Definitions used for key codes from a PS2 keyboard, do not use in your + code these are handled by the library. + + See PS2KeyAdvanced.h for codes returned from library and flag settings + + Two sets of tables + + Single Byte codes returned as key codes + + Two byte Codes preceded by E0 code returned as keycodes + + Same tables used for make and break decode + + Special cases are - + + PRTSCR that ignores one of the sequences (E0,12) as this is not always sent + especially with modifier keys or some keyboards when typematic repeat comes on. + + PAUSE as this is an 8 byte sequence only one starting E1 so main code gets E1 + and waits for 7 more valid bytes to make the coding. + + 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 +*/ +#ifndef PS2KeyTable_h +#define PS2KeyTable_h + +/* Table contents are pairs of numbers + first code from keyboard + second is either PS2_KEY_IGNOPRE code or key code to return + + Single byte Key table + In codes can only be 1 - 0x9F, plus 0xF2 and 0xF1 + Out Codes in range 1 to 0x9F +*/ +#if defined(PS2_REQUIRES_PROGMEM) +const uint8_t PROGMEM single_key[][ 2 ] = { +#else +const uint8_t single_key[][ 2 ] = { +#endif + { PS2_KC_NUM, PS2_KEY_NUM }, + { PS2_KC_SCROLL, PS2_KEY_SCROLL }, + { PS2_KC_CAPS, PS2_KEY_CAPS }, + { PS2_KC_L_SHIFT, PS2_KEY_L_SHIFT }, + { PS2_KC_R_SHIFT, PS2_KEY_R_SHIFT }, + { PS2_KC_CTRL, PS2_KEY_L_CTRL }, + { PS2_KC_ALT, PS2_KEY_L_ALT }, + { PS2_KC_SYSRQ, PS2_KEY_SYSRQ }, + { PS2_KC_ESC, PS2_KEY_ESC }, + { PS2_KC_BS, PS2_KEY_BS }, + { PS2_KC_TAB, PS2_KEY_TAB }, + { PS2_KC_ENTER, PS2_KEY_ENTER }, + { PS2_KC_SPACE, PS2_KEY_SPACE }, + { PS2_KC_KP0, PS2_KEY_KP0 }, + { PS2_KC_KP1, PS2_KEY_KP1 }, + { PS2_KC_KP2, PS2_KEY_KP2 }, + { PS2_KC_KP3, PS2_KEY_KP3 }, + { PS2_KC_KP4, PS2_KEY_KP4 }, + { PS2_KC_KP5, PS2_KEY_KP5 }, + { PS2_KC_KP6, PS2_KEY_KP6 }, + { PS2_KC_KP7, PS2_KEY_KP7 }, + { PS2_KC_KP8, PS2_KEY_KP8 }, + { PS2_KC_KP9, PS2_KEY_KP9 }, + { PS2_KC_KP_DOT, PS2_KEY_KP_DOT }, + { PS2_KC_KP_PLUS, PS2_KEY_KP_PLUS }, + { PS2_KC_KP_MINUS, PS2_KEY_KP_MINUS }, + { PS2_KC_KP_TIMES, PS2_KEY_KP_TIMES }, + { PS2_KC_KP_EQUAL, PS2_KEY_KP_EQUAL }, + { PS2_KC_0, PS2_KEY_0 }, + { PS2_KC_1, PS2_KEY_1 }, + { PS2_KC_2, PS2_KEY_2 }, + { PS2_KC_3, PS2_KEY_3 }, + { PS2_KC_4, PS2_KEY_4 }, + { PS2_KC_5, PS2_KEY_5 }, + { PS2_KC_6, PS2_KEY_6 }, + { PS2_KC_7, PS2_KEY_7 }, + { PS2_KC_8, PS2_KEY_8 }, + { PS2_KC_9, PS2_KEY_9 }, + { PS2_KC_APOS, PS2_KEY_APOS }, + { PS2_KC_COMMA, PS2_KEY_COMMA }, + { PS2_KC_MINUS, PS2_KEY_MINUS }, + { PS2_KC_DOT, PS2_KEY_DOT }, + { PS2_KC_DIV, PS2_KEY_DIV }, + { PS2_KC_SINGLE, PS2_KEY_SINGLE }, + { PS2_KC_A, PS2_KEY_A }, + { PS2_KC_B, PS2_KEY_B }, + { PS2_KC_C, PS2_KEY_C }, + { PS2_KC_D, PS2_KEY_D }, + { PS2_KC_E, PS2_KEY_E }, + { PS2_KC_F, PS2_KEY_F }, + { PS2_KC_G, PS2_KEY_G }, + { PS2_KC_H, PS2_KEY_H }, + { PS2_KC_I, PS2_KEY_I }, + { PS2_KC_J, PS2_KEY_J }, + { PS2_KC_K, PS2_KEY_K }, + { PS2_KC_L, PS2_KEY_L }, + { PS2_KC_M, PS2_KEY_M }, + { PS2_KC_N, PS2_KEY_N }, + { PS2_KC_O, PS2_KEY_O }, + { PS2_KC_P, PS2_KEY_P }, + { PS2_KC_Q, PS2_KEY_Q }, + { PS2_KC_R, PS2_KEY_R }, + { PS2_KC_S, PS2_KEY_S }, + { PS2_KC_T, PS2_KEY_T }, + { PS2_KC_U, PS2_KEY_U }, + { PS2_KC_V, PS2_KEY_V }, + { PS2_KC_W, PS2_KEY_W }, + { PS2_KC_X, PS2_KEY_X }, + { PS2_KC_Y, PS2_KEY_Y }, + { PS2_KC_Z, PS2_KEY_Z }, + { PS2_KC_SEMI, PS2_KEY_SEMI }, + { PS2_KC_BACK, PS2_KEY_BACK }, + { PS2_KC_OPEN_SQ, PS2_KEY_OPEN_SQ }, + { PS2_KC_CLOSE_SQ, PS2_KEY_CLOSE_SQ }, + { PS2_KC_EQUAL, PS2_KEY_EQUAL }, + { PS2_KC_EUROPE2, PS2_KEY_EUROPE2 }, + { PS2_KC_F1, PS2_KEY_F1 }, + { PS2_KC_F2, PS2_KEY_F2 }, + { PS2_KC_F3, PS2_KEY_F3 }, + { PS2_KC_F4, PS2_KEY_F4 }, + { PS2_KC_F5, PS2_KEY_F5 }, + { PS2_KC_F6, PS2_KEY_F6 }, + { PS2_KC_F7, PS2_KEY_F7 }, + { PS2_KC_F8, PS2_KEY_F8 }, + { PS2_KC_F9, PS2_KEY_F9 }, + { PS2_KC_F10, PS2_KEY_F10 }, + { PS2_KC_F11, PS2_KEY_F11 }, + { PS2_KC_F12, PS2_KEY_F12 }, + { PS2_KC_F13, PS2_KEY_F13 }, + { PS2_KC_F14, PS2_KEY_F14 }, + { PS2_KC_F15, PS2_KEY_F15 }, + { PS2_KC_F16, PS2_KEY_F16 }, + { PS2_KC_F17, PS2_KEY_F17 }, + { PS2_KC_F18, PS2_KEY_F18 }, + { PS2_KC_F19, PS2_KEY_F19 }, + { PS2_KC_F20, PS2_KEY_F20 }, + { PS2_KC_F21, PS2_KEY_F21 }, + { PS2_KC_F22, PS2_KEY_F22 }, + { PS2_KC_F23, PS2_KEY_F23 }, + { PS2_KC_F24, PS2_KEY_F24 }, + { PS2_KC_KP_COMMA, PS2_KEY_KP_COMMA }, + { PS2_KC_INTL1, PS2_KEY_INTL1 }, + { PS2_KC_INTL2, PS2_KEY_INTL2 }, + { PS2_KC_INTL3, PS2_KEY_INTL3 }, + { PS2_KC_INTL4, PS2_KEY_INTL4 }, + { PS2_KC_INTL5, PS2_KEY_INTL5 }, + { PS2_KC_LANG1, PS2_KEY_LANG1 }, + { PS2_KC_LANG2, PS2_KEY_LANG2 }, + { PS2_KC_LANG3, PS2_KEY_LANG3 }, + { PS2_KC_LANG4, PS2_KEY_LANG4 }, + { PS2_KC_LANG5, PS2_KEY_LANG5 } + }; + +/* Two byte Key table after an E0 byte received */ +#if defined(PS2_REQUIRES_PROGMEM) +const uint8_t PROGMEM extended_key[][ 2 ] = { +#else +const uint8_t extended_key[][ 2 ] = { +#endif + { PS2_KC_IGNORE, PS2_KEY_IGNORE }, + { PS2_KC_PRTSCR, PS2_KEY_PRTSCR }, + { PS2_KC_CTRL, PS2_KEY_R_CTRL }, + { PS2_KC_ALT, PS2_KEY_R_ALT }, + { PS2_KC_L_GUI, PS2_KEY_L_GUI }, + { PS2_KC_R_GUI, PS2_KEY_R_GUI }, + { PS2_KC_MENU, PS2_KEY_MENU }, + { PS2_KC_BREAK, PS2_KEY_BREAK }, + { PS2_KC_HOME, PS2_KEY_HOME }, + { PS2_KC_END, PS2_KEY_END }, + { PS2_KC_PGUP, PS2_KEY_PGUP }, + { PS2_KC_PGDN, PS2_KEY_PGDN }, + { PS2_KC_L_ARROW, PS2_KEY_L_ARROW }, + { PS2_KC_R_ARROW, PS2_KEY_R_ARROW }, + { PS2_KC_UP_ARROW, PS2_KEY_UP_ARROW }, + { PS2_KC_DN_ARROW, PS2_KEY_DN_ARROW }, + { PS2_KC_INSERT, PS2_KEY_INSERT }, + { PS2_KC_DELETE, PS2_KEY_DELETE }, + { PS2_KC_KP_ENTER, PS2_KEY_KP_ENTER }, + { PS2_KC_KP_DIV, PS2_KEY_KP_DIV }, + { PS2_KC_NEXT_TR, PS2_KEY_NEXT_TR }, + { PS2_KC_PREV_TR, PS2_KEY_PREV_TR }, + { PS2_KC_STOP, PS2_KEY_STOP }, + { PS2_KC_PLAY, PS2_KEY_PLAY }, + { PS2_KC_MUTE, PS2_KEY_MUTE }, + { PS2_KC_VOL_UP, PS2_KEY_VOL_UP }, + { PS2_KC_VOL_DN, PS2_KEY_VOL_DN }, + { PS2_KC_MEDIA, PS2_KEY_MEDIA }, + { PS2_KC_EMAIL, PS2_KEY_EMAIL }, + { PS2_KC_CALC, PS2_KEY_CALC }, + { PS2_KC_COMPUTER, PS2_KEY_COMPUTER }, + { PS2_KC_WEB_SEARCH, PS2_KEY_WEB_SEARCH }, + { PS2_KC_WEB_HOME, PS2_KEY_WEB_HOME }, + { PS2_KC_WEB_BACK, PS2_KEY_WEB_BACK }, + { PS2_KC_WEB_FORWARD, PS2_KEY_WEB_FORWARD }, + { PS2_KC_WEB_STOP, PS2_KEY_WEB_STOP }, + { PS2_KC_WEB_REFRESH, PS2_KEY_WEB_REFRESH }, + { PS2_KC_WEB_FAVOR, PS2_KEY_WEB_FAVOR }, + { PS2_KC_POWER, PS2_KEY_POWER }, + { PS2_KC_SLEEP, PS2_KEY_SLEEP }, + { PS2_KC_WAKE, PS2_KEY_WAKE } + }; + +/* Scroll lock numeric keypad re-mappings for NOT NUMLOCK */ +/* in translated code order order is important */ +#if defined(PS2_REQUIRES_PROGMEM) +const uint8_t PROGMEM scroll_remap[] = { +#else +const uint8_t scroll_remap[] = { +#endif + PS2_KEY_INSERT, // PS2_KEY_KP0 + PS2_KEY_END, // PS2_KEY_KP1 + PS2_KEY_DN_ARROW, // PS2_KEY_KP2 + PS2_KEY_PGDN, // PS2_KEY_KP3 + PS2_KEY_L_ARROW, // PS2_KEY_KP4 + PS2_KEY_IGNORE, // PS2_KEY_KP5 + PS2_KEY_R_ARROW, // PS2_KEY_KP6 + PS2_KEY_HOME, // PS2_KEY_KP7 + PS2_KEY_UP_ARROW, // PS2_KEY_KP8 + PS2_KEY_PGUP, // PS2_KEY_KP9 + PS2_KEY_DELETE // PS2_KEY_KP_DOT + }; +#endif