├── LICENSE ├── README.md ├── examples ├── KeyToLCD │ └── KeyToLCD.ino ├── SimpleTest │ └── SimpleTest.ino └── advcodetest │ └── advcodetest.ino ├── extra ├── Images │ ├── NUMLock-02-FA.png │ ├── NUMLock-77.png │ ├── NUMLock-ED-FA.png │ └── NUMLock-sequence.PNG ├── PS2 Keyboard.pdf ├── Porting.md ├── codes.txt ├── readme.txt └── websites.txt ├── keywords.txt ├── library.properties └── src ├── PS2KeyAdvanced.cpp ├── PS2KeyAdvanced.h ├── PS2KeyCode.h └── PS2KeyTable.h /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | (This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.) 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | {description} 474 | Copyright (C) {year} {fullname} 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | {signature of Ty Coon}, 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PS2KeyAdvanced 2 | ## Arduino PS2 Keyboard FULL keyboard protocol support and full keys to integer coding 3 | **V1.0.10** October 2021 - Fix PS2_KEY_PAUSE value and RX/TX barrier on _PS2_BUSY on transmissions 4 | 5 | Smaller footprint than any others found and more functionality. 6 | 7 | For other versions that just read the keycodes for all keyboard types or allow you to get the full UTF-8 configurable for any LATIN keyboard with 8 | extra functions keys as simple codes see associated repository for [PS2KeyMap library](https://github.com/techpaul/PS2KeyMap). Yes these libraries even provide codes 9 | for multimedia keys and Function keys F1 to F24 (yes that is F24). 10 | 11 | ### IMPORTANT NOTE ON SCAN CODE SETS 12 | 13 | PS2 keyboard spec specifies THREE Scan Code Sets, however **ONLY SET 2 IS GUARANTEED**. 14 | 15 | - Scan Code Set 1 is the old XT mode rarely available on keyboards 16 | - Scan Code Set 2 is the **default** Scan Code Set guaranteed to work 17 | - Scan Code Set 3 is even rarer to find keyboards that support it. Long abandoned by manufacturers. 18 | 19 | **This library ONLY supports Scan Code Set 2** 20 | 21 | ### Platforms known to have been tested on 22 | 23 | - Arduino AVR - tested on Uno and Mega 2560 (Users have tested on Teensy 2.0 and Teensy++ 2.0) 24 | - Arduino SAM - tested on DUE 25 | - SAMD1 - Seeeduino Xiao M0+ (tested by user) 26 | - STM32 - STM32Duino-Framework and PlatformIO on STM32F103C8T6 from user Hiabuto-de 27 | - ESP32 - ESP32 (arduino-esp32) from users dharmik768 and n6il 28 | 29 | See later for porting to other platforms 30 | 31 | ### Test Environment 32 | 33 | - All Arduino platforms versions of test R3 Hardware 34 | - Arduino V1.6.7 and newer 35 | - DUE Board Manager package V1.6.6 or higher 36 | 37 | ### Important Hardware Notes 38 | 39 | 1. Make sure you have data and clock wires connected correctly. Clock wire MUST be connected to an interrupt pin. 40 | 41 | - Do NOT use Pin 13 for either clock or data wires 42 | - PS2KeyAdvanced requires both pins specified for begin() as in keyboard.begin( data_pin, irq_pin ); 43 | - Valid irq pins: 44 | - Arduino Uno: 2, 3 45 | - Arduino Due: All pins, except 13 (LED) 46 | - Arduino Mega: 2, 3, 18, 19, 20, 21 47 | - Teensy 2.0: All pins, except 13 (LED) 48 | - Teensy 2.0: 5, 6, 7, 8 49 | - Teensy 1.0: 0, 1, 2, 3, 4, 6, 7, 16 50 | - Teensy++ 2.0: 0, 1, 2, 3, 18, 19, 36, 37 51 | - Teensy++ 1.0: 0, 1, 2, 3, 18, 19, 36, 37 52 | - Sanguino: 2, 10, 11 53 | 54 | 2. When using DUE or other boards with 3V3 I/O you MUST use a level translator FET or IC like Texas Instruments TXS0102 or similar as most keyboards 55 | not only operate at 5V but the two wire communications are pulled up by a resistor to 5V at the keyboard end. 56 | 3. USB keyboards through PS2 adapter draw **LOTS** of current and can cause processor and/or keyboard to RESET if not EXTERNALLY POWERED. It is best 57 | to work with 'native' PS2 keyboards. 58 | 59 | ## Introduction 60 | After looking round for suitable libraries I found most were lacking in functionality and high in code and data footprint, so I created a series of 61 | PS2 Keyboard libraries. This is the second which fully supports the PS2 Keyboard Protocol, even allowing you control of keyboard LEDs (some have 4 62 | LEDs) and changing settings.. 63 | 64 | The PS2 Keyboard interface is still needed for systems that have no USB and even if you have USB, you want it left for other uses. 65 | 66 | The PS2 Keyboard interface is a Bi-directional two wire interface with a clock line and a data line which you connect to your Arduino (see above), 67 | the keyboard protocol has many nuances all of which are used in the other libraries of this series. this library allows you to access the keycodes 68 | sent from a keyboard into its small buffer and read out the codes with simple methods. 69 | 70 | Returns any keypress as 16 bit integer, which includes a coded value for the key along with status for 71 | 72 | - Make/Break 73 | - CTRL, SHIFT, CAPS, ALT, GUI, ALT-GR Status 74 | - Alphanumeric/keyboard Function 75 | - 8 bit key code (defined in public header) 76 | 77 | Fully featured PS2 keyboard library to provide 78 | 79 | - All keys have a keycode (ESC, A-Z and 0-9 as ASCII equivalents) 80 | - All function (F1 to F24), multimedia and movement keys supported 81 | - Parity checking of data sent/received 82 | - Resends data and requests resends when needed 83 | - Functions for get and/or set of 84 | - Scancode set in use 85 | - LED and LOCK control 86 | - ReadID 87 | - Reset keyboard 88 | - Send ECHO 89 | - Ignore Break codes for keys 90 | - Ignore typematic repeat of CTRL, SHIFT, ALT, Num, Scroll, Caps 91 | - Handles NUM, CAPS and SCROLL lock keys to LEDs 92 | - Handles NUM/SCROLL internally 93 | 94 | ### Installation 95 | Performed by standard zip file library inclusion into Arduino IDE 96 | 97 | ### IDE Configuration 98 | It is recommended that users compile with ALL errors and warnings displayed in Arduino IDE, to perform this select 99 | menu functions 100 | 101 | File --> Preferences 102 | 103 | - On "Show verbose output during" Select "Compiling" 104 | - On next line "Compiler Warnings" select "All" 105 | - Select "OK" 106 | - Restart IDE and test compile an example. 107 | 108 | ### Examples 109 | This library has THREE examples, from simplest to most complex - 110 | 111 | - SimpleTest that uses the serial port to output the converted codes received on every keystroke and auto-repeat. 112 | - advcodetest that uses serial port and some of the keys pressed to send commands back to the keyboard to see the responses for things like Reset 113 | keyboard, Read ID, change Typematic rate (auto-repeat). 114 | - KeyToLCD - Example that will allow you to display keyboard actions on LCD connected to Arduino and allow cursor movements to move the cursor on 115 | LCD, whilst also displaying strings for keys like ESC, TAB, F1 to F12 116 | 117 | ## Porting to different boards or architectures 118 | See document Porting.md in extra folder for hints to assist in this process 119 | ### Version History 120 | 121 | | Version | Date | | Description | 122 | |:--|:--:|---|:--| 123 | |V1.0.10| October 2021 | | Fix PS2_KEY_PAUSE value and RX/TX barrier on _PS2_BUSY on transmissions. | 124 | |V1.0.9| July 2021 | | Add ESP32 support from user submissions. See [Issue #21](https://github.com/techpaul/PS2KeyAdvanced/issues/21)| 125 | |V1.0.8| November 2020 | | Add support for STM32 from user Hiabuto-de. Tested on STM32Duino-Framework and PlatformIO on STM32F103C8T6 and an IBM Model M| 126 | |V1.0.7| March 2020 | | Add notes for porting to other platforms, tidy ups, add SAMD1| 127 | |V1.0.6| January 2020 | | Fix typos, correct keyboard reset status improve library.properties and additional reduction for easier platform handling| 128 | |V1.0.4| August 2018 | | Minor reduction in available() method to remove redundant extra safety checks on buffers| 129 | |V1.0.3| July 2018 | | Improved keywords file| 130 | 131 | First Public Release Version V1.0.2 132 | ### Contributor and Author Details 133 | Author Paul Carpenter, PC Services 134 | 135 | Web Site http://www.pcserviceselectronics.co.uk 136 | -------------------------------------------------------------------------------- /examples/KeyToLCD/KeyToLCD.ino: -------------------------------------------------------------------------------- 1 | /* Test for PS2KeyAdvanced and LiquidCrystal 2 | 3 | IMPORTANT WARNING 4 | 5 | If using a DUE or similar board with 3V3 I/O you MUST put a level translator 6 | like a Texas Instruments TXS0102 or FET circuit as the signals are 7 | Bi-directional (signals transmitted from both ends on same wire). 8 | 9 | Failure to do so may damage your Arduino Due or similar board. 10 | 11 | Test History 12 | September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 13 | January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board 14 | Manager V1.6.6 15 | 16 | This sketch displays text received from PS2 keyboard to LCD on same Arduino. 17 | Allows the cursor movement keys as follows - 18 | 19 | Enter move to beginning of next line and wraps to top 20 | PGUP and PGDN go to top and bottom row in same column of LCD 21 | Arrow keys move one line or character and wrap round rows 22 | Backspace does backspace space backspace sequence 23 | Home goes to top left 24 | End goes to bottom right 25 | Keys TAB DEL ESC and F1 to F12 are displayed as strings 26 | 27 | All typing and some cursor movements wrap to appropriate line forwards 28 | and backwards 29 | 30 | Example works on any size text LCD, set for 16 x 2 31 | Change MAX_COL and MAX_ROW to match your LCD 32 | 33 | Also example of strings in flash memory 34 | 35 | Displayable characters passed through (depends on LCD character set) 36 | 37 | Note some keys are not displayed properly as the PS2KeyAdvanced 38 | returns a key coding of which some are ASCII. See examples for PS2KeyMap 39 | if you want full displayable character set. 40 | 41 | Also example of strings and string array in flash memory 42 | 43 | The circuit: 44 | * LCD RS pin to digital pin 12 45 | * LCD Enable pin to digital pin 11 46 | * LCD D4 pin to digital pin 10 47 | * LCD D5 pin to digital pin 9 48 | * LCD D6 pin to digital pin 8 49 | * LCD D7 pin to digital pin 7 50 | * LCD R/W pin to ground 51 | * 10K variable resistor (trimmer or potentiometer): 52 | - ends to +5V and ground 53 | - wiper to LCD VO pin (pin 3) 54 | * KBD Clock (PS2 pin 1) to an interrupt pin on Arduino ( this example pin 3 ) 55 | * KBD Data (PS2 pin 5) to a data pin ( this example pin 4 ) 56 | * +5V from Arduino to PS2 pin 4 57 | * GND from Arduino to PS2 pin 3 58 | 59 | The connector to mate with PS2 keyboard is a 6 pin Female Mini-Din connector 60 | PS2 Pins to signal 61 | 1 KBD Data 62 | 3 GND 63 | 4 +5V 64 | 5 KBD Clock 65 | 66 | Keyboard has 5V and GND connected see plenty of examples and 67 | photos around on Arduino site and other sites about the PS2 Connector. 68 | 69 | Interrupts 70 | 71 | Clock pin from PS2 keyboard MUST be connected to an interrupt 72 | pin, these vary with the different types of Arduino 73 | 74 | For PS2KeyAdvanced you pass this info into begin() 75 | 76 | keyboard.begin( DATAPIN, IRQPIN ); 77 | 78 | Valid irq pins: 79 | Arduino Uno: 2, 3 80 | Arduino Due: All pins, except 13 (LED) 81 | Arduino Mega: 2, 3, 18, 19, 20, 21 82 | Teensy 2.0: All pins, except 13 (LED) 83 | Teensy 2.0: 5, 6, 7, 8 84 | Teensy 1.0: 0, 1, 2, 3, 4, 6, 7, 16 85 | Teensy++ 2.0: 0, 1, 2, 3, 18, 19, 36, 37 86 | Teensy++ 1.0: 0, 1, 2, 3, 18, 19, 36, 37 87 | Sanguino: 2, 10, 11 88 | 89 | Like the Original library and example this is under LGPL license. 90 | 91 | Written by Paul Carpenter, PC Services 92 | */ 93 | 94 | // include the library code: 95 | #include 96 | #include 97 | 98 | /* Keyboard constants Change to suit your Arduino 99 | define pins used for data and clock from keyboard */ 100 | #define DATAPIN 4 101 | #define IRQPIN 3 102 | 103 | /* LCD pins definitions to match your LCD 4 bit mode */ 104 | #define RS 12 105 | #define ENA 11 106 | #define RW 10 107 | #define D7 9 108 | #define D6 8 109 | #define D5 7 110 | #define D4 6 111 | 112 | /* LCD Constants to match your display */ 113 | /* Columns in display */ 114 | #define MAX_COL 16 115 | /* Rows in display */ 116 | #define MAX_ROW 2 117 | 118 | /* current cursor position */ 119 | int8_t cols = 0; 120 | int8_t rows = 0; 121 | 122 | /* messages constants */ 123 | /* Key codes and strings for keys producing a string */ 124 | /* three arrays in same order ( keycode, string to display, length of string ) */ 125 | #if defined(PS2_REQUIRES_PROGMEM) 126 | const uint8_t codes[] PROGMEM = { PS2_KEY_SPACE, PS2_KEY_TAB, PS2_KEY_ESC, PS2_KEY_DELETE, 127 | PS2_KEY_F1, PS2_KEY_F2, PS2_KEY_F3, PS2_KEY_F4, 128 | PS2_KEY_F5, PS2_KEY_F6, PS2_KEY_F7, PS2_KEY_F8, 129 | PS2_KEY_F9, PS2_KEY_F10, PS2_KEY_F11, PS2_KEY_F12 }; 130 | const char spacestr[] PROGMEM = " "; 131 | const char tabstr[] PROGMEM = "[Tab]"; 132 | const char escstr[] PROGMEM = "[ESC]"; 133 | const char delstr[] PROGMEM = "[Del]"; 134 | const char f1str[] PROGMEM = "[F1]"; 135 | const char f2str[] PROGMEM = "[F2]"; 136 | const char f3str[] PROGMEM = "[F3]"; 137 | const char f4str[] PROGMEM = "[F4]"; 138 | const char f5str[] PROGMEM = "[F5]"; 139 | const char f6str[] PROGMEM = "[F6]"; 140 | const char f7str[] PROGMEM = "[F7]"; 141 | const char f8str[] PROGMEM = "[F8]"; 142 | const char f9str[] PROGMEM = "[F9]"; 143 | const char f10str[] PROGMEM = "[F10]"; 144 | const char f11str[] PROGMEM = "[F11]"; 145 | const char f12str[] PROGMEM = "[F12]"; 146 | 147 | // Due to AVR Harvard architecture array of string pointers to actual strings 148 | const char *const keys[] PROGMEM = { 149 | spacestr, tabstr, escstr, delstr, f1str, f2str, 150 | f3str, f4str, f5str, f6str, f7str, f8str, 151 | f9str, f10str, f11str, f12str }; 152 | const int8_t sizes[] PROGMEM = { 1, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5 }; 153 | char buffer[ 8 ]; 154 | 155 | #else 156 | const uint8_t codes[] = { PS2_KEY_SPACE, PS2_KEY_TAB, PS2_KEY_ESC, 157 | PS2_KEY_DELETE, PS2_KEY_F1, PS2_KEY_F2, PS2_KEY_F3, 158 | PS2_KEY_F4, PS2_KEY_F5, PS2_KEY_F6, PS2_KEY_F7, 159 | PS2_KEY_F8, PS2_KEY_F9, PS2_KEY_F10, PS2_KEY_F11, 160 | PS2_KEY_F12 }; 161 | const char *const keys[] = { " ", "[Tab]", "[ESC]", "[Del]", "[F1]", "[F2]", "[F3]", 162 | "[F4]", "[F5]", "[F6]", "[F7]", "[F8]", 163 | "[F9]", "[F10]", "[F11]", "[F12]" }; 164 | const int8_t sizes[] = { 1, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5 }; 165 | #endif 166 | 167 | // initialize the keyboard library with the numbers of the interface pins 168 | PS2KeyAdvanced keyboard; 169 | 170 | // initialize the LCD library with the numbers of the interface pins 171 | // For 4 bit interface first with RW pin grounded on LCD 172 | //LiquidCrystal lcd( RS, ENA, D4, D5, D6, D7 ); 173 | LiquidCrystal lcd( RS, RW, ENA, D4, D5, D6, D7 ); 174 | 175 | 176 | void setup() 177 | { 178 | keyboard.begin( DATAPIN, IRQPIN );// Setup keyboard pins 179 | keyboard.setNoBreak( 1 ); // No break codes for keys (when key released) 180 | keyboard.setNoRepeat( 1 ); // Don't repeat shift ctrl etc 181 | 182 | // set up the LCD's number of columns and rows 183 | lcd.begin( MAX_COL, MAX_ROW ); 184 | lcd.clear(); // clear the screen 185 | lcd.cursor(); // Enable Cursor 186 | lcd.blink(); // Blinking cursor 187 | lcd.print( "PC Services" ); // Display sign-on text 188 | lcd.setCursor( 0,1 ); 189 | lcd.print( "Keyboard to LCD" ); 190 | lcd.setCursor( 12,0 ); 191 | cols = 12; // update cursor position 192 | rows = 0; 193 | } 194 | 195 | 196 | /* Check if cursor now moved beyond end of column */ 197 | void check_cursor() 198 | { 199 | if( cols >= MAX_COL ) 200 | { 201 | cols = 0; 202 | rows++; 203 | if( rows >= MAX_ROW ) 204 | rows = 0; 205 | lcd.setCursor( cols, rows ); 206 | } 207 | } 208 | 209 | 210 | void loop() 211 | { 212 | /* mode = 0 echo character 213 | mode = 1 print string 214 | mode = 2 cursor movement NO other echo 215 | mode = 4 ignore key no echo */ 216 | byte mode = 0; 217 | byte idx = 0; 218 | int c = 0; 219 | 220 | if( keyboard.available() ) 221 | { 222 | // read the next key 223 | if( (c = keyboard.read()) ) 224 | { 225 | // check for some of the special keys 226 | mode = 2; 227 | c &= 0xFF; 228 | switch( c ) /* Cursor movements */ 229 | { 230 | case PS2_KEY_ENTER: /* Cursor to beginning of next line or start */ 231 | case PS2_KEY_KP_ENTER: 232 | cols = 0; 233 | rows++; 234 | if( rows >= MAX_ROW ) 235 | rows = 0; 236 | break; 237 | case PS2_KEY_PGDN: /* Cursor to top row current column */ 238 | rows = MAX_ROW - 1; 239 | break; 240 | case PS2_KEY_PGUP: /* Cursor to bottom row current column */ 241 | rows = 0; 242 | break; 243 | case PS2_KEY_L_ARROW: /* Cursor left or end of previous line */ 244 | cols--; 245 | if( cols < 0 ) 246 | { 247 | cols = MAX_COL - 1; 248 | rows--; 249 | if( rows < 0 ) 250 | rows = MAX_ROW - 1; 251 | } 252 | break; 253 | case PS2_KEY_R_ARROW: /* Cursor right or start of next line */ 254 | cols++; 255 | if( cols >= MAX_COL ) 256 | { 257 | cols = 0; 258 | rows++; 259 | if( rows >= MAX_COL ) 260 | rows = 0; 261 | } 262 | break; 263 | case PS2_KEY_UP_ARROW: /* Cursor up one line no wrap */ 264 | rows--; 265 | if( rows < 0 ) 266 | rows = 0; 267 | break; 268 | case PS2_KEY_DN_ARROW: /* Cursor down one line no wrap */ 269 | rows++; 270 | if( rows >= MAX_ROW ) 271 | rows = MAX_ROW - 1; 272 | break; 273 | case PS2_KEY_BS: /* Move cursor back write space move cursor back */ 274 | cols--; 275 | if( cols < 0 ) 276 | { 277 | cols = MAX_COL - 1; 278 | rows--; 279 | if( rows < 0 ) 280 | rows = MAX_ROW - 1; 281 | } 282 | lcd.setCursor( cols, rows ); 283 | lcd.write( ' ' ); 284 | break; 285 | case PS2_KEY_HOME: /* Cursor to top left */ 286 | cols = 0; 287 | rows = 0; 288 | break; 289 | case PS2_KEY_END: /* Cursor to max position */ 290 | cols = MAX_COL - 1; 291 | rows = MAX_ROW - 1; 292 | break; 293 | default: /* Not cursor movement */ 294 | mode = 0; 295 | } 296 | /* if was cursor movement do last movement */ 297 | if( mode == 2 ) 298 | lcd.setCursor( cols, rows ); 299 | else 300 | { 301 | /* Check for strings or single character to display */ 302 | /* Function or similar key */ 303 | if( c != PS2_KEY_EUROPE2 && ( c < PS2_KEY_KP0 || c >= PS2_KEY_F1 ) ) 304 | { // Non printable sort which ones we can print 305 | for( idx = 0; idx < sizeof( codes ); idx++ ) 306 | #if defined(PS2_REQUIRES_PROGMEM) 307 | if( c == pgm_read_byte( codes + idx ) ) 308 | #else 309 | if( c == codes[ idx ] ) 310 | #endif 311 | { /* String outputs */ 312 | mode = 1; 313 | #if defined(PS2_REQUIRES_PROGMEM) 314 | c = pgm_read_byte( sizes + idx ); 315 | #else 316 | c = sizes[ idx ]; 317 | #endif 318 | cols += c - 1; 319 | check_cursor( ); 320 | /* when cursor reset keep track */ 321 | if( cols == 0 ) 322 | cols = c; 323 | #if defined(PS2_REQUIRES_PROGMEM) 324 | strcpy_P( buffer, (char*)pgm_read_word( &( keys[ idx ] ) ) ); 325 | lcd.print( buffer ); 326 | #else 327 | lcd.print( keys[ idx ] ); 328 | #endif 329 | cols++; 330 | check_cursor( ); 331 | break; 332 | } 333 | /* if not found a string ignore key cant do anything */ 334 | } 335 | else 336 | { /* Supported key */ 337 | if( c <= 127 || c > 0 ) 338 | { 339 | check_cursor( ); 340 | cols++; 341 | lcd.write( c ); 342 | check_cursor( ); 343 | } 344 | } 345 | } 346 | } 347 | delay( 100 ); 348 | } 349 | } 350 | -------------------------------------------------------------------------------- /examples/SimpleTest/SimpleTest.ino: -------------------------------------------------------------------------------- 1 | /* Simple keyboard to serial port at 115200 baud 2 | 3 | PS2KeyAdvanced library example 4 | 5 | Advanced support PS2 Keyboard to get every key code byte from a PS2 Keyboard 6 | for testing purposes. 7 | 8 | IMPORTANT WARNING 9 | 10 | If using a DUE or similar board with 3V3 I/O you MUST put a level translator 11 | like a Texas Instruments TXS0102 or FET circuit as the signals are 12 | Bi-directional (signals transmitted from both ends on same wire). 13 | 14 | Failure to do so may damage your Arduino Due or similar board. 15 | 16 | Test History 17 | September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 18 | January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board 19 | Manager V1.6.6 20 | 21 | This is for a LATIN style keyboard using Scan code set 2. See various 22 | websites on what different scan code sets use. Scan Code Set 2 is the 23 | default scan code set for PS2 keyboards on power up. 24 | 25 | Will support most keyboards even ones with multimedia keys or even 24 function keys. 26 | 27 | The circuit: 28 | * KBD Clock (PS2 pin 1) to an interrupt pin on Arduino ( this example pin 3 ) 29 | * KBD Data (PS2 pin 5) to a data pin ( this example pin 4 ) 30 | * +5V from Arduino to PS2 pin 4 31 | * GND from Arduino to PS2 pin 3 32 | 33 | The connector to mate with PS2 keyboard is a 6 pin Female Mini-Din connector 34 | PS2 Pins to signal 35 | 1 KBD Data 36 | 3 GND 37 | 4 +5V 38 | 5 KBD Clock 39 | 40 | Keyboard has 5V and GND connected see plenty of examples and 41 | photos around on Arduino site and other sites about the PS2 Connector. 42 | 43 | Interrupts 44 | 45 | Clock pin from PS2 keyboard MUST be connected to an interrupt 46 | pin, these vary with the different types of Arduino 47 | 48 | PS2KeyAdvanced requires both pins specified for begin() 49 | 50 | keyboard.begin( data_pin, irq_pin ); 51 | 52 | Valid irq pins: 53 | Arduino Uno: 2, 3 54 | Arduino Due: All pins, except 13 (LED) 55 | Arduino Mega: 2, 3, 18, 19, 20, 21 56 | Teensy 2.0: All pins, except 13 (LED) 57 | Teensy 2.0: 5, 6, 7, 8 58 | Teensy 1.0: 0, 1, 2, 3, 4, 6, 7, 16 59 | Teensy++ 2.0: 0, 1, 2, 3, 18, 19, 36, 37 60 | Teensy++ 1.0: 0, 1, 2, 3, 18, 19, 36, 37 61 | Sanguino: 2, 10, 11 62 | 63 | Read method Returns an UNSIGNED INT containing 64 | Make/Break status 65 | Caps status 66 | Shift, CTRL, ALT, ALT GR, GUI keys 67 | Flag for function key not a displayable/printable character 68 | 8 bit key code 69 | 70 | Code Ranges (bottom byte of unsigned int) 71 | 0 invalid/error 72 | 1-1F Functions (Caps, Shift, ALT, Enter, DEL... ) 73 | 1A-1F Functions with ASCII control code 74 | (DEL, BS, TAB, ESC, ENTER, SPACE) 75 | 20-61 Printable characters noting 76 | 0-9 = 0x30 to 0x39 as ASCII 77 | A to Z = 0x41 to 0x5A as upper case ASCII type codes 78 | 8B Extra European key 79 | 61-A0 Function keys and other special keys (plus F2 and F1) 80 | 61-78 F1 to F24 81 | 79-8A Multimedia 82 | 8B NOT included 83 | 8C-8E ACPI power 84 | 91-A0 and F2 and F1 - Special multilingual 85 | A8-FF Keyboard communications commands (note F2 and F1 are special 86 | codes for special multi-lingual keyboards) 87 | 88 | By using these ranges it is possible to perform detection of any key and do 89 | easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code. 90 | 91 | Top Byte is 8 bits denoting as follows with defines for bit code 92 | 93 | Define name bit description 94 | PS2_BREAK 15 1 = Break key code 95 | (MSB) 0 = Make Key code 96 | PS2_SHIFT 14 1 = Shift key pressed as well (either side) 97 | 0 = NO shift key 98 | PS2_CTRL 13 1 = Ctrl key pressed as well (either side) 99 | 0 = NO Ctrl key 100 | PS2_CAPS 12 1 = Caps Lock ON 101 | 0 = Caps lock OFF 102 | PS2_ALT 11 1 = Left Alt key pressed as well 103 | 0 = NO Left Alt key 104 | PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well 105 | 0 = NO Right Alt key 106 | PS2_GUI 9 1 = GUI key pressed as well (either) 107 | 0 = NO GUI key 108 | PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter) 109 | 0 = standard character key 110 | 111 | Error Codes 112 | Most functions return 0 or 0xFFFF as error, other codes to note and 113 | handle appropriately 114 | 0xAA keyboard has reset and passed power up tests 115 | will happen if keyboard plugged in after code start 116 | 0xFC Keyboard General error or power up fail 117 | 118 | See PS2Keyboard.h file for returned definitions of Keys 119 | 120 | Note defines starting 121 | PS2_KEY_* are the codes this library returns 122 | PS2_* remaining defines for use in higher levels 123 | 124 | To get the key as ASCII/UTF-8 single byte character conversion requires use 125 | of PS2KeyMap library AS WELL. 126 | 127 | Written by Paul Carpenter, PC Services 128 | */ 129 | 130 | #include 131 | 132 | /* Keyboard constants Change to suit your Arduino 133 | define pins used for data and clock from keyboard */ 134 | #define DATAPIN 4 135 | #define IRQPIN 3 136 | 137 | uint16_t c; 138 | 139 | PS2KeyAdvanced keyboard; 140 | 141 | 142 | void setup( ) 143 | { 144 | // Configure the keyboard library 145 | keyboard.begin( DATAPIN, IRQPIN ); 146 | Serial.begin( 115200 ); 147 | Serial.println( "PS2 Advanced Key Simple Test:" ); 148 | } 149 | 150 | 151 | void loop( ) 152 | { 153 | if( keyboard.available( ) ) 154 | { 155 | // read the next key 156 | c = keyboard.read( ); 157 | if( c > 0 ) 158 | { 159 | Serial.print( "Value " ); 160 | Serial.print( c, HEX ); 161 | Serial.print( " - Status Bits " ); 162 | Serial.print( c >> 8, HEX ); 163 | Serial.print( " Code " ); 164 | Serial.println( c & 0xFF, HEX ); 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /examples/advcodetest/advcodetest.ino: -------------------------------------------------------------------------------- 1 | /* Advanced keyboard example test to serial port at 115200 with command setting 2 | 3 | PS2KeyAdvanced library example 4 | 5 | Advanced support PS2 Keyboard to get every key code byte from a PS2 Keyboard 6 | for testing purposes. Enables capture of all keys output to serial monitor. 7 | 8 | IMPORTANT WARNING 9 | 10 | If using a DUE or similar board with 3V3 I/O you MUST put a level translator 11 | like a Texas Instruments TXS0102 or FET circuit as the signals are 12 | Bi-directional (signals transmitted from both ends on same wire). 13 | 14 | Failure to do so may damage your Arduino Due or similar board. 15 | 16 | Test History 17 | September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 18 | January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board 19 | Manager V1.6.6 20 | 21 | This is for a LATIN style keyboard using Scan code set 2. See various 22 | websites on what different scan code sets use. Scan Code Set 2 is the 23 | default scan code set for PS2 keyboards on power up. 24 | 25 | Will support most keyboards even ones with multimedia keys or even 24 function keys. 26 | 27 | Also allows keys entered to send commands to keyboard as follows 28 | R = Reset Send reset command to keyboard and get responses 29 | E = Echo Send protocol ECHO command (0xEE) and get same back 30 | I = ReadID Read the keyboard ID code ( should 2 bytes 0xAb 0x83) 31 | S = Scancode Get current Scancode set in use on keyboard should be 2 32 | T = Typematic rate Set to slowest Rate and delay 33 | G = Current Lock Get the current lock status (num, scroll, caps) 34 | B = Break codes Toggle if receiving break codes is on or off 35 | N = No repeat Ignore repeats of make codes for Shift, Ctrl, ALT, ALT-GR, GUI 36 | 37 | The circuit: 38 | * KBD Clock (PS2 pin 1) to an interrupt pin on Arduino ( this example pin 3 ) 39 | * KBD Data (PS2 pin 5) to a data pin ( this example pin 4 ) 40 | * +5V from Arduino to PS2 pin 4 41 | * GND from Arduino to PS2 pin 3 42 | 43 | The connector to mate with PS2 keyboard is a 6 pin Female Mini-Din connector 44 | PS2 Pins to signal 45 | 1 KBD Data 46 | 3 GND 47 | 4 +5V 48 | 5 KBD Clock 49 | 50 | Keyboard has 5V and GND connected see plenty of examples and 51 | photos around on Arduino site and other sites about the PS2 Connector. 52 | 53 | Interrupts 54 | 55 | Clock pin from PS2 keyboard MUST be connected to an interrupt 56 | pin, these vary with the different types of Arduino 57 | 58 | PS2KeyAdvanced requires both pins specified for begin( ) 59 | 60 | keyboard.begin( data_pin, irq_pin ); 61 | 62 | Valid irq pins: 63 | Arduino Uno: 2, 3 64 | Arduino Due: All pins, except 13 (LED) 65 | Arduino Mega: 2, 3, 18, 19, 20, 21 66 | Teensy 2.0: All pins, except 13 (LED) 67 | Teensy 2.0: 5, 6, 7, 8 68 | Teensy 1.0: 0, 1, 2, 3, 4, 6, 7, 16 69 | Teensy++ 2.0: 0, 1, 2, 3, 18, 19, 36, 37 70 | Teensy++ 1.0: 0, 1, 2, 3, 18, 19, 36, 37 71 | Sanguino: 2, 10, 11 72 | 73 | Read method Returns an UNSIGNED INT containing 74 | Make/Break status 75 | Caps status 76 | Shift, CTRL, ALT, ALT GR, GUI keys 77 | Flag for function key not a displayable/printable character 78 | 8 bit key code 79 | 80 | Code Ranges (bottom byte of unsigned int) 81 | 0 invalid/error 82 | 1-1F Functions (Caps, Shift, ALT, Enter, DEL... ) 83 | 1A-1F Functions with ASCII control code 84 | (DEL, BS, TAB, ESC, ENTER, SPACE) 85 | 20-61 Printable characters noting 86 | 0-9 = 0x30 to 0x39 as ASCII 87 | A to Z = 0x41 to 0x5A as upper case ASCII type codes 88 | 8B Extra European key 89 | 61-A0 Function keys and other special keys (plus F2 and F1) 90 | 61-78 F1 to F24 91 | 79-8A Multimedia 92 | 8B NOT included 93 | 8C-8E ACPI power 94 | 91-A0 and F2 and F1 - Special multilingual 95 | A8-FF Keyboard communications commands (note F2 and F1 are special 96 | codes for special multi-lingual keyboards) 97 | 98 | By using these ranges it is possible to perform detection of any key and do 99 | easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code. 100 | 101 | Top Byte is 8 bits denoting as follows with defines for bit code 102 | 103 | Define name bit description 104 | PS2_BREAK 15 1 = Break key code 105 | (MSB) 0 = Make Key code 106 | PS2_SHIFT 14 1 = Shift key pressed as well (either side) 107 | 0 = NO shift key 108 | PS2_CTRL 13 1 = Ctrl key pressed as well (either side) 109 | 0 = NO Ctrl key 110 | PS2_CAPS 12 1 = Caps Lock ON 111 | 0 = Caps lock OFF 112 | PS2_ALT 11 1 = Left Alt key pressed as well 113 | 0 = NO Left Alt key 114 | PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well 115 | 0 = NO Right Alt key 116 | PS2_GUI 9 1 = GUI key pressed as well (either) 117 | 0 = NO GUI key 118 | PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter) 119 | 0 = standard character key 120 | 121 | Error Codes 122 | Most functions return 0 or 0xFFFF as error, other codes to note and 123 | handle appropriately 124 | 0xAA keyboard has reset and passed power up tests 125 | will happen if keyboard plugged in after code start 126 | 0xFC Keyboard General error or power up fail 127 | 128 | See PS2Keyboard.h file for returned definitions of Keys 129 | 130 | Note defines starting 131 | PS2_KEY_* are the codes this library returns 132 | PS2_* remaining defines for use in higher levels 133 | 134 | To get the key as ASCII/UTF-8 single byte character conversion requires use 135 | of PS2KeyMap library AS WELL. 136 | 137 | Written by Paul Carpenter, PC Services 138 | */ 139 | 140 | #include 141 | 142 | /* Keyboard constants Change to suit your Arduino 143 | define pins used for data and clock from keyboard */ 144 | #define DATAPIN 4 145 | #define IRQPIN 3 146 | 147 | uint16_t c; 148 | uint8_t breaks = 0; 149 | uint8_t repeats = 0; 150 | 151 | PS2KeyAdvanced keyboard; 152 | 153 | 154 | void setup( ) 155 | { 156 | Serial.begin( 115200 ); 157 | Serial.println( "PS2 Advanced Key - Advanced Test:" ); 158 | 159 | // Configure the keyboard library 160 | keyboard.begin( DATAPIN, IRQPIN ); 161 | keyboard.echo( ); // ping keyboard to see if there 162 | delay( 6 ); 163 | c = keyboard.read( ); 164 | if( (c & 0xFF) == PS2_KEY_ECHO 165 | || (c & 0xFF) == PS2_KEY_BAT ) 166 | Serial.println( "Keyboard OK.." ); // Response was Echo or power up 167 | else 168 | if( ( c & 0xFF ) == 0 ) 169 | Serial.println( "Keyboard Not Found" ); 170 | else 171 | { 172 | Serial.print( "Invalid Code received of " ); 173 | Serial.println( c, HEX ); 174 | } 175 | } 176 | 177 | 178 | void loop( ) 179 | { 180 | if( keyboard.available( ) ) 181 | { 182 | // read the next key 183 | c = keyboard.read( ); 184 | if( ( c & 0xFF ) > 0 ) 185 | Serial.println( c , HEX ); 186 | /* now do something with keys entered results on serial monitor */ 187 | if( !( c & PS2_BREAK ) ) // only on make codes 188 | switch( c & 0xFF ) 189 | { 190 | case PS2_KEY_R: 191 | Serial.println( "Reset" ); 192 | keyboard.resetKey( ); // Reset keyboard 193 | break; 194 | case PS2_KEY_S: 195 | Serial.println( "Get Scancode set in use" ); 196 | keyboard.getScanCodeSet( ); // Get which scan code set 197 | break; 198 | case PS2_KEY_G: 199 | Serial.print( "Get current lock status = " ); 200 | c = keyboard.getLock( ); // Get current lock status 201 | Serial.println( c, HEX ); 202 | break; 203 | case PS2_KEY_I: 204 | Serial.println( "Read ID code" ); 205 | keyboard.readID( ); // Get which scan code set 206 | break; 207 | case PS2_KEY_E: 208 | Serial.println( "Echo" ); 209 | keyboard.echo( ); 210 | break; 211 | case PS2_KEY_T: 212 | Serial.println( "Typematic Rate" ); 213 | keyboard.typematic( 31, 3); // Get slowest 214 | break; 215 | case PS2_KEY_B: 216 | Serial.print( "No Break Codes " ); 217 | breaks ^= 1;; 218 | Serial.println( breaks ); 219 | keyboard.setNoBreak( breaks ); // set break mode 220 | break; 221 | case PS2_KEY_N: 222 | Serial.print( "No Repeat Makes for CTRL... " ); 223 | repeats ^= 1; 224 | Serial.println( repeats ); 225 | keyboard.setNoRepeat( repeats ); // Set repeat mode 226 | break; 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /extra/Images/NUMLock-02-FA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techpaul/PS2KeyAdvanced/7294fea7e9813f84282e36668ab755a5ee5d1899/extra/Images/NUMLock-02-FA.png -------------------------------------------------------------------------------- /extra/Images/NUMLock-77.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techpaul/PS2KeyAdvanced/7294fea7e9813f84282e36668ab755a5ee5d1899/extra/Images/NUMLock-77.png -------------------------------------------------------------------------------- /extra/Images/NUMLock-ED-FA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techpaul/PS2KeyAdvanced/7294fea7e9813f84282e36668ab755a5ee5d1899/extra/Images/NUMLock-ED-FA.png -------------------------------------------------------------------------------- /extra/Images/NUMLock-sequence.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techpaul/PS2KeyAdvanced/7294fea7e9813f84282e36668ab755a5ee5d1899/extra/Images/NUMLock-sequence.PNG -------------------------------------------------------------------------------- /extra/PS2 Keyboard.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techpaul/PS2KeyAdvanced/7294fea7e9813f84282e36668ab755a5ee5d1899/extra/PS2 Keyboard.pdf -------------------------------------------------------------------------------- /extra/Porting.md: -------------------------------------------------------------------------------- 1 | # PS2KeyAdvanced - Porting to New Boards or Architectures 2 | This document assumes you have some low level understanding of your board, Arduino library structures and the compiler for your board. 3 | 4 | The majority of assists you require are in PS2KeyAdvanced.h the main header file for the library which has some architecture specific defines. 5 | 6 | When a valid supported architecture is supported this flag is set. Without this set for a **VALID** architecture that is supported 7 | a compiler warning or hard error is reported on compiling. 8 | 9 | - PS2_SUPPORTED 10 | 11 | These are to cope with AVR Harvard architecture, AVR and SAM (many but not all architectures) issue of *not* clearing past events on Interrupt pin 12 | before attachInterrupt enables interrupts those causing false interrupt events. 13 | 14 | - PS2_REQUIRES_PROGMEM 15 | - PS2_CLEAR_PENDING_IRQ 16 | 17 | The following is to cope with architectures that use CHANGE interrupt even when asking for FALLING. 18 | - PS2_ONLY_CHANGE_IRQ 19 | 20 | ## General Rules 21 | To add another board type you need to make some changes 22 | 1. You need to determine what the define is for your architecture, as AVR uses ARDUINO_ARCH_AVR so from verbose compiling output you need to find 23 | the part in compiling output for YOUR BOARD that should be **-DARDUINO_ARCH_xxxx**. Where the "xxxx" is the board architecture. You need this for 24 | making later changes. 25 | 2. In PS2KeyAdvanced.h you need to add a specific test for your board after the AVR and SAM checks (Note PS2_SUPPORTED **must** be included in your 26 | test otherwise a compilation error will occur.) like 27 | ~~~ 28 | #if defined( ARDUINO_ARCH_xxxx ) 29 | #define PS2_SUPPORTED 1 30 | #define PS2_REQUIRES_PROGMEM 1 31 | #endif 32 | ~~~ 33 | 3. Change library.properties to add your architecture to the comma separated list for your architecture, normally this is the "xxxx" for ARCH_ARDUINO_xxxx 34 | 35 | If your architecture needs an **EXTRA** flag then it must have a name describing the functionality the flag enables 36 | **NOT** the board or architecture name. this means it is easier to be readable to others and may also be needed for other 37 | other boards or architectures. 38 | ### PS2_SUPPORTED 39 | This flag is set to indicate we have a supported board, this flag stops a compiler error being forced. 40 | 41 | To enable for your architecture add a line in the '#if' for your architecture as follows 42 | ~~~ 43 | #define PS2_SUPPORTED 1 44 | ~~~ 45 | ### PS2_REQUIRES_PROGMEM 46 | This determines that to have constants in Flash memory not RAM on AVR boards the PROGMEM functions have to be used. 47 | 48 | To enable for your architecture add a line in the '#if' for your architecture as follows 49 | ~~~ 50 | #define PS2_REQUIRES_PROGMEM 1 51 | ~~~ 52 | ### PS2_CLEAR_PENDING_IRQ 53 | When sending data to the keyboard, interrupts have to be turned off and back on again, on AVR and SAM architecture any changes on the clock pin 54 | cause extra interrupts when attachInterrupt is used to start bit timing interrupts again, on other architectures this does not normally happen so we 55 | need to change how many interrupt events we see for a valid byte sending. This does not affect receiving data just the sending. 56 | 57 | This defines adds an extra bit clock event interrupt step for AVR and SAM 58 | 59 | To enable for your architecture add a line in the '#if' for your architecture as follows 60 | ~~~ 61 | #define PS2_CLEAR_PENDING_IRQ 1 62 | ~~~ 63 | ### PS2_ONLY_CHANGE_IRQ 64 | This came about when the processor or the board package does not support all types of interrupt, the library uses 65 | FALLING (falling edge when signal goes from high to low), some processors or board packages do not implement this 66 | and use CHANGE interrupt (both edges) even if you ask for one edge. 67 | 68 | To enable for your architecture add a line in the '#if' for your architecture as follows 69 | ~~~ 70 | #define PS2_ONLY_CHANGE_IRQ 1 71 | ~~~ 72 | This was first required for ESP32, which has a SILICON (hardware) MCU problem and workarounds **SHOULD** have been incorporated into arduino-esp32 73 | https://github.com/espressif/arduino-esp32 The issue there are **SPURIOUS** extra interrupts. 74 | ## Support of changes 75 | If you can test **ALL** functionality working, you are welcome to do a pull request from your github fork of this library. If this meets our coding 76 | guidelines and you can show it is has been working it will include in next release. 77 | 78 | Please note whilst we can give assistance, we probably do not have your board or maybe not the time to incorporate full support for you. of course we 79 | can always accept standard commercial daily rates to this for your, if you are made of money and willing for result to be publicly available for free. 80 | -------------------------------------------------------------------------------- /extra/codes.txt: -------------------------------------------------------------------------------- 1 | Constants to use in decoding keyboard values from PS2KeyAdvanced 2 | 3 | Copyright (c) 2007 Free Software Foundation. All right reserved. 4 | Written by Paul Carpenter, PC Services 5 | Created January 2016 - Paul Carpenter 6 | 7 | Keyboard responses you may see 8 | 9 | PS2_KEY_ACK 10 | PS2_KEY_ECHO 11 | PS2_KEY_BAT 12 | PS2_KEY_OVERRUN 13 | PS2_KEY_ERROR 14 | 15 | Parameter data for setting Keyboard LEDs (add together) 16 | 17 | PS2_LOCK_SCROLL 18 | PS2_LOCK_NUM 19 | PS2_LOCK_CAPS 20 | PS2_LOCK_EXTRA (for keyboards with 4th LED) 21 | 22 | The definitions of extra combinations SHIFT etc (add together) 23 | 24 | PS2_BREAK 25 | PS2_SHIFT 26 | PS2_CTRL 27 | PS2_CAPS 28 | PS2_ALT 29 | PS2_ALT_GR 30 | PS2_GUI 31 | PS2_FUNCTION 32 | 33 | Returned keycode definitions for all possible keys, 34 | NOT all codes returned for all keyboards 35 | 36 | PS2_KEY_NUM 37 | PS2_KEY_SCROLL 38 | PS2_KEY_CAPS 39 | PS2_KEY_PRTSCR 40 | PS2_KEY_PAUSE 41 | PS2_KEY_L_SHIFT 42 | PS2_KEY_R_SHIFT 43 | PS2_KEY_L_CTRL 44 | PS2_KEY_R_CTRL 45 | PS2_KEY_L_ALT 46 | PS2_KEY_R_ALT 47 | PS2_KEY_L_GUI (Sometimes called windows key) 48 | PS2_KEY_R_GUI (Sometimes called windows key) 49 | PS2_KEY_MENU 50 | PS2_KEY_BREAK (Break is CTRL + PAUSE generated inside keyboard) 51 | PS2_KEY_SYSRQ (Generated by some keyboards by ALT and PRTSCR )0x10 52 | PS2_KEY_HOME 53 | PS2_KEY_END 54 | PS2_KEY_PGUP 55 | PS2_KEY_PGDN 56 | PS2_KEY_L_ARROW 57 | PS2_KEY_R_ARROW 58 | PS2_KEY_UP_ARROW 59 | PS2_KEY_DN_ARROW 60 | PS2_KEY_INSERT 61 | PS2_KEY_DELETE 62 | PS2_KEY_ESC 63 | PS2_KEY_BS 64 | PS2_KEY_TAB 65 | PS2_KEY_ENTER 66 | PS2_KEY_SPACE 67 | PS2_KEY_KP0 68 | PS2_KEY_KP1 69 | PS2_KEY_KP2 70 | PS2_KEY_KP3 71 | PS2_KEY_KP4 72 | PS2_KEY_KP5 73 | PS2_KEY_KP6 74 | PS2_KEY_KP7 75 | PS2_KEY_KP8 76 | PS2_KEY_KP9 77 | PS2_KEY_KP_DOT 78 | PS2_KEY_KP_ENTER 79 | PS2_KEY_KP_PLUS 80 | PS2_KEY_KP_MINUS 81 | PS2_KEY_KP_TIMES 82 | PS2_KEY_KP_DIV 83 | PS2_KEY_0 84 | PS2_KEY_1 85 | PS2_KEY_2 86 | PS2_KEY_3 87 | PS2_KEY_4 88 | PS2_KEY_5 89 | PS2_KEY_6 90 | PS2_KEY_7 91 | PS2_KEY_8 92 | PS2_KEY_9 93 | PS2_KEY_APOS 94 | PS2_KEY_COMMA 95 | PS2_KEY_MINUS 96 | PS2_KEY_DOT 97 | PS2_KEY_DIV 98 | PS2_KEY_KP_EQUAL (Some Numeric keyboards have an '=' on right keypad) 99 | PS2_KEY_SINGLE (Single quote or back quote) 100 | PS2_KEY_A 101 | PS2_KEY_B 102 | PS2_KEY_C 103 | PS2_KEY_D 104 | PS2_KEY_E 105 | PS2_KEY_F 106 | PS2_KEY_G 107 | PS2_KEY_H 108 | PS2_KEY_I 109 | PS2_KEY_J 110 | PS2_KEY_K 111 | PS2_KEY_L 112 | PS2_KEY_M 113 | PS2_KEY_N 114 | PS2_KEY_O 115 | PS2_KEY_P 116 | PS2_KEY_Q 117 | PS2_KEY_R 118 | PS2_KEY_S 119 | PS2_KEY_T 120 | PS2_KEY_U 121 | PS2_KEY_V 122 | PS2_KEY_W 123 | PS2_KEY_X 124 | PS2_KEY_Y 125 | PS2_KEY_Z 126 | PS2_KEY_SEMI 127 | PS2_KEY_BACK 128 | PS2_KEY_OPEN_SQ 129 | PS2_KEY_CLOSE_SQ 130 | PS2_KEY_EQUAL 131 | PS2_KEY_KP_COMMA (Some Numeric keypads have a comma key) 132 | PS2_KEY_F1 133 | PS2_KEY_F2 134 | PS2_KEY_F3 135 | PS2_KEY_F4 136 | PS2_KEY_F5 137 | PS2_KEY_F6 138 | PS2_KEY_F7 139 | PS2_KEY_F8 140 | PS2_KEY_F9 141 | PS2_KEY_F10 142 | PS2_KEY_F11 143 | PS2_KEY_F12 144 | PS2_KEY_F13 145 | PS2_KEY_F14 146 | PS2_KEY_F15 147 | PS2_KEY_F16 148 | PS2_KEY_F17 149 | PS2_KEY_F18 150 | PS2_KEY_F19 151 | PS2_KEY_F20 152 | PS2_KEY_F21 153 | PS2_KEY_F22 154 | PS2_KEY_F23 155 | PS2_KEY_F24 156 | PS2_KEY_NEXT_TR 157 | PS2_KEY_PREV_TR 158 | PS2_KEY_STOP 159 | PS2_KEY_PLAY 160 | PS2_KEY_MUTE 161 | PS2_KEY_VOL_UP 162 | PS2_KEY_VOL_DN 163 | PS2_KEY_MEDIA 164 | PS2_KEY_EMAIL 165 | PS2_KEY_CALC 166 | PS2_KEY_COMPUTER 167 | PS2_KEY_WEB_SEARCH 168 | PS2_KEY_WEB_HOME 169 | PS2_KEY_WEB_BACK 170 | PS2_KEY_WEB_FORWARD 171 | PS2_KEY_WEB_STOP 172 | PS2_KEY_WEB_REFRESH 173 | PS2_KEY_WEB_FAVOR 174 | PS2_KEY_EUROPE2 175 | PS2_KEY_POWER 176 | PS2_KEY_SLEEP 177 | PS2_KEY_WAKE 178 | PS2_KEY_INTL1 179 | PS2_KEY_INTL2 180 | PS2_KEY_INTL3 181 | PS2_KEY_INTL4 182 | PS2_KEY_INTL5 183 | PS2_KEY_LANG1 184 | PS2_KEY_LANG2 185 | PS2_KEY_LANG3 186 | PS2_KEY_LANG4 187 | PS2_KEY_LANG5 188 | -------------------------------------------------------------------------------- /extra/readme.txt: -------------------------------------------------------------------------------- 1 | PS2KeyAdvanced - PS2KeyAdvanced library 2 | Copyright (c) 2007 Free Software Foundation. All right reserved. 3 | Written by Paul Carpenter, PC Services 4 | Created September 2014 5 | Updated January 2016 6 | Updated February 2020 7 | 8 | This is for a LATIN style keyboard. 9 | 10 | Assumption ONLY ONE keyboard connected to system 11 | 12 | Fully featured PS2 keyboard library to provide 13 | All keys have a keycode (ESC, A-Z and 0-9 as ASCII equivalents) 14 | All function and movement keys supported 15 | Parity checking of data sent/received 16 | Resends data and requests resends when needed 17 | Functions for get and/or set of 18 | Scancode set in use 19 | LED and LOCK control 20 | ReadID 21 | Reset keyboard 22 | Send ECHO 23 | Ignore Break codes for keys 24 | Ignore typematic repeat of CTRL, SHIFT, ALT, Num, Scroll, Caps 25 | Handles NUM, CAPS and SCROLL lock keys to LEDs 26 | Handles NUM/SCROLL internally 27 | 28 | Makes it easier to catch key combinations like press of + or 29 | + + . 30 | 31 | You can even detect repetitions or not of keys or even when a key is released. 32 | 33 | See extras\codes.txt for useful defines available in the library for key codes 34 | and combinations. Note often codes like oxFA are received from the keyboard 35 | after commands are sent this code is the ACKNOWLEDGE data from the keyboard 36 | to say received correctly. 37 | 38 | See also file extras\websites.txt for website information about PS2 interface, 39 | protocol scancodes and UTF-8 encoding. 40 | 41 | Files are 42 | 43 | extras folder 44 | codes.txt The literals (constants) you can use to match codes returned 45 | PS2 Keyboard.pdf Copy of Website explaining PS2 Protocol 46 | readme.txt this file 47 | websites.txt Other websites about PS2 keyboard and UTF-8 character encoding 48 | Images folder containing images for a single NUMLOCK keypress and what 49 | happens on the wires. 50 | 51 | src folder 52 | PS2KeyAdvanced.cpp the library code 53 | PS2KeyAdvanced.h Library Header for sketches defines class and values returned for keys 54 | PS2KeyCode.h internal header file for codes from actual keyboard 55 | PS2KeyTable.h internal table of translations from keyboard to return code 56 | 57 | examples folder 58 | SimpleTest reads every returned keycode back to serial (to get codes for mapping) 59 | advcodetest reads keyboard and sends codes in hex to serial 60 | KeyToLCD reads keyboard and displays where possible on LCD 61 | 62 | A full protocol handshake for the sequence of pressing the NUMLOCK key and 63 | then turning on the NUMLOCK LED is shown as a set of scope screenshots in 64 | extras\Images . These are 65 | 66 | NUMLock-sequence.PNG The complete sequence (both ways) 67 | 68 | In detail the other images highlight parts of the sequence - 69 | 70 | NUMLock-77.png keyboard sends NUMLOCK byte (0x77) 71 | 72 | NUMLock-ED-FA.png Arduino sends light LEDs command (0xED) 73 | keyboard responds ACKNOWLEDGE (0xFA) 74 | 75 | NUMLock-02-FA.png Arduino sends data for LED combination (0x02) 76 | keyboard responds ACKNOWLEDGE (0xFA) 77 | 78 | Reading a key code returns an UNSIGNED INT containing 79 | Make/Break status 80 | Caps status 81 | Shift, Ctrl, Alt, Alt Gr, GUI keys 82 | Flag for function key not a displayable/printable character 83 | 8 bit key code 84 | 85 | To get the key as ASCII/UTF-8 single byte character conversion requires use 86 | of PS2KeyMap library AS WELL. 87 | 88 | Code Ranges (bottom byte of unsigned int) 89 | 0 invalid/error 90 | 1-1F Functions (caps, shift, alt, enter, del... ) 91 | 1A-1F Functions with ASCII control code (DEL, BS, TAB, ESC, ENTER, SPACE) 92 | 20-60 Printable characters noting 93 | 0-9 = 0x30 to 0x39 as ASCII 94 | A to Z = 0x41 to 0x5A as upper case ASCII type codes 95 | 61-9F Function keys and other special keys (plus F2 and F1) 96 | 61-78 F1 to F24 97 | 79-8A Multimedia 98 | 8B-8D ACPI power 99 | 90-9F Special multilingual 100 | A0-FF Keyboard communications commands (note F2 and F1 are special 101 | codes for special multi-lingual keyboards) 102 | 103 | By using these ranges it is possible to perform detection of any key and do 104 | easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code. 105 | See code defines below for how to decode top byte. 106 | 107 | Top Byte is 8 bits denoting as follows and standard defines available - 108 | 109 | Define name bit description 110 | PS2_BREAK 15 1 = Break key code 111 | (MSB) 0 = Make Key code 112 | PS2_SHIFT 14 1 = Shift key pressed as well (either) 113 | 0 = NO shift key 114 | PS2_CTRL 13 1 = Ctrl key pressed as well (either) 115 | 0 = NO Ctrl key 116 | PS2_CAPS 12 1 = Caps Lock ON 117 | 0 = Caps lock OFF 118 | PS2_ALT 11 1 = Left Alt key pressed as well 119 | 0 = NO Left Alt key 120 | PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well 121 | 0 = NO Right Alt key 122 | PS2_GUI 9 1 = GUI key pressed as well (either) 123 | 0 = NO GUI key 124 | PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter) 125 | 0 = standard character key 126 | 127 | Error Codes 128 | Most functions return 0 or 0xFFFF as error, other codes to note and 129 | handle appropriately, which are responses from the keyboard - 130 | 131 | 0xAA keyboard has reset and passed power up tests 132 | will happen if keyboard plugged in after code start 133 | 0xFC keyboard failed power up tests 134 | 135 | It is responsibility of your programme to deal with converting special cases 136 | like + sends a special value to something else. 137 | 138 | See extras\codes.txt for codes from the keyboard this library uses to decode. 139 | These are defines so that you can use a standard name for ANY key without 140 | knowing the actual value. 141 | 142 | Returned Keycodes in lower half of unsigned integer returned are detailed in 143 | extras\codes.txt 144 | 145 | Parameters for other functions are 146 | =================================== 147 | 148 | For Typematic Rate (repeat rate and delay to repeat), setting two parameters 149 | first value 0 to 0x1F as per table below 150 | second value defines listed below 151 | 152 | Typematic (repeat) Rate use codes in Rate column and (repeat) delay defines 153 | Rate CPS Rate CPS Rate CPS Rate CPS 154 | ------------------------------------------------------------ 155 | 0 30 8 15 10 7.5 18 3.7 156 | 1 26.7 9 13.3 11 6.7 19 3.3 157 | 2 24 A 12 12 6 1A 3 158 | 3 21.8 B 10.9 13 5.5 1B 2.7 159 | 4 20.7 C 10 14 5 1C 2.5 160 | 5 18.5 D 9.2 15 4.6 1D 2.3 161 | 6 17.1 E 8.6 16 4.3 1E 2.1 162 | 7 16 F 8 17 4 1F 2 163 | 164 | Delay define 165 | -------------------------- 166 | 0.25 seconds PS2_DELAY0 167 | 0.5 seconds PS2_DELAY1 168 | 0.75 seconds PS2_DELAY2 169 | 1 second PS2_DELAY3 170 | 171 | For LEDs command use the following defines added together to set them 172 | PS2_LOCK_SCROLL 173 | PS2_LOCK_NUM 174 | PS2_LOCK_CAPS 175 | PS2_LOCK_EXTRA (for keyboards with 4th LED) 176 | 177 | 178 | Paul Carpenter 179 | PC Services 180 | February 2020 181 | http://www.pcserviceselectronics.co.uk -------------------------------------------------------------------------------- /extra/websites.txt: -------------------------------------------------------------------------------- 1 | Some URLs of useful technical sites that give you the inner workings details 2 | of the PS2 Keyboard interface, not in any order, many have pictures on - 3 | 4 | PS2 Interface, Keyboard and scan codes 5 | 6 | https://en.wikipedia.org/wiki/PS/2_port 7 | http://www.computer-engineering.org/ps2keyboard/ 8 | http://computer-engineering.org/ps2protocol/ 9 | http://retired.beyondlogic.org/keyboard/keybrd.htm 10 | http://wiki.osdev.org/PS/2_Keyboard 11 | 12 | UTF-8 13 | http://www.utf8-chartable.de/unicode-utf8-table.pl?utf8=char 14 | 15 | Old Arduino site library page 16 | http://playground.arduino.cc/Main/PS2Keyboard -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For PS2KeyADV 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes/class (KEYWORD1) 7 | ####################################### 8 | PS2KeyAdvanced KEYWORD1 9 | 10 | ####################################### 11 | # Methods and Functions (KEYWORD2) 12 | ####################################### 13 | available KEYWORD2 14 | read KEYWORD2 15 | readID KEYWORD2 16 | echo KEYWORD2 17 | getLock KEYWORD2 18 | setLock KEYWORD2 19 | resetKey KEYWORD2 20 | getScanCodeSet KEYWORD2 21 | setNoRepeat KEYWORD2 22 | setNoBreak KEYWORD2 23 | typematic KEYWORD2 24 | 25 | ####################################### 26 | # Constants (LITERAL1) 27 | ####################################### 28 | PS2_BREAK LITERAL1 29 | PS2_SHIFT LITERAL1 30 | PS2_CTRL LITERAL1 31 | PS2_CAPS LITERAL1 32 | PS2_ALT LITERAL1 33 | PS2_ALT_GR LITERAL1 34 | PS2_GUI LITERAL1 35 | PS2_FUNCTION LITERAL1 36 | PS2_KEY_RESEND LITERAL1 37 | PS2_KEY_ACK LITERAL1 38 | PS2_KEY_ECHO LITERAL1 39 | PS2_KEY_BAT LITERAL1 40 | PS2_KEY_OVERRUN LITERAL1 41 | PS2_KEY_ERROR LITERAL1 42 | PS2_LOCK_SCROLL LITERAL1 43 | PS2_LOCK_NUM LITERAL1 44 | PS2_LOCK_CAPS LITERAL1 45 | PS2_LOCK_EXTRA LITERAL1 46 | PS2_KEY_NUM LITERAL1 47 | PS2_KEY_SCROLL LITERAL1 48 | PS2_KEY_CAPS LITERAL1 49 | PS2_KEY_PRTSCR LITERAL1 50 | PS2_KEY_PAUSE LITERAL1 51 | PS2_KEY_L_SHIFT LITERAL1 52 | PS2_KEY_R_SHIFT LITERAL1 53 | PS2_KEY_L_CTRL LITERAL1 54 | PS2_KEY_R_CTRL LITERAL1 55 | PS2_KEY_L_ALT LITERAL1 56 | PS2_KEY_R_ALT LITERAL1 57 | PS2_KEY_L_GUI LITERAL1 58 | PS2_KEY_R_GUI LITERAL1 59 | PS2_KEY_MENU LITERAL1 60 | PS2_KEY_BREAK LITERAL1 61 | PS2_KEY_SYSRQ LITERAL1 62 | PS2_KEY_HOME LITERAL1 63 | PS2_KEY_END LITERAL1 64 | PS2_KEY_PGUP LITERAL1 65 | PS2_KEY_PGDN LITERAL1 66 | PS2_KEY_L_ARROW LITERAL1 67 | PS2_KEY_R_ARROW LITERAL1 68 | PS2_KEY_UP_ARROW LITERAL1 69 | PS2_KEY_DN_ARROW LITERAL1 70 | PS2_KEY_INSERT LITERAL1 71 | PS2_KEY_DELETE LITERAL1 72 | PS2_KEY_ESC LITERAL1 73 | PS2_KEY_BS LITERAL1 74 | PS2_KEY_TAB LITERAL1 75 | PS2_KEY_ENTER LITERAL1 76 | PS2_KEY_SPACE LITERAL1 77 | PS2_KEY_KP0 LITERAL1 78 | PS2_KEY_KP1 LITERAL1 79 | PS2_KEY_KP2 LITERAL1 80 | PS2_KEY_KP3 LITERAL1 81 | PS2_KEY_KP4 LITERAL1 82 | PS2_KEY_KP5 LITERAL1 83 | PS2_KEY_KP6 LITERAL1 84 | PS2_KEY_KP7 LITERAL1 85 | PS2_KEY_KP8 LITERAL1 86 | PS2_KEY_KP9 LITERAL1 87 | PS2_KEY_KP_DOT LITERAL1 88 | PS2_KEY_KP_ENTER LITERAL1 89 | PS2_KEY_KP_PLUS LITERAL1 90 | PS2_KEY_KP_MINUS LITERAL1 91 | PS2_KEY_KP_TIMES LITERAL1 92 | PS2_KEY_KP_DIV LITERAL1 93 | PS2_KEY_0 LITERAL1 94 | PS2_KEY_1 LITERAL1 95 | PS2_KEY_2 LITERAL1 96 | PS2_KEY_3 LITERAL1 97 | PS2_KEY_4 LITERAL1 98 | PS2_KEY_5 LITERAL1 99 | PS2_KEY_6 LITERAL1 100 | PS2_KEY_7 LITERAL1 101 | PS2_KEY_8 LITERAL1 102 | PS2_KEY_9 LITERAL1 103 | PS2_KEY_APOS LITERAL1 104 | PS2_KEY_COMMA LITERAL1 105 | PS2_KEY_MINUS LITERAL1 106 | PS2_KEY_DOT LITERAL1 107 | PS2_KEY_DIV LITERAL1 108 | PS2_KEY_SINGLE LITERAL1 109 | PS2_KEY_KP_EQUAL LITERAL1 110 | PS2_KEY_A LITERAL1 111 | PS2_KEY_B LITERAL1 112 | PS2_KEY_C LITERAL1 113 | PS2_KEY_D LITERAL1 114 | PS2_KEY_E LITERAL1 115 | PS2_KEY_F LITERAL1 116 | PS2_KEY_G LITERAL1 117 | PS2_KEY_H LITERAL1 118 | PS2_KEY_I LITERAL1 119 | PS2_KEY_J LITERAL1 120 | PS2_KEY_K LITERAL1 121 | PS2_KEY_L LITERAL1 122 | PS2_KEY_M LITERAL1 123 | PS2_KEY_N LITERAL1 124 | PS2_KEY_O LITERAL1 125 | PS2_KEY_P LITERAL1 126 | PS2_KEY_Q LITERAL1 127 | PS2_KEY_R LITERAL1 128 | PS2_KEY_S LITERAL1 129 | PS2_KEY_T LITERAL1 130 | PS2_KEY_U LITERAL1 131 | PS2_KEY_V LITERAL1 132 | PS2_KEY_W LITERAL1 133 | PS2_KEY_X LITERAL1 134 | PS2_KEY_Y LITERAL1 135 | PS2_KEY_Z LITERAL1 136 | PS2_KEY_SEMI LITERAL1 137 | PS2_KEY_BACK LITERAL1 138 | PS2_KEY_OPEN_SQ LITERAL1 139 | PS2_KEY_CLOSE_SQ LITERAL1 140 | PS2_KEY_EQUAL LITERAL1 141 | PS2_KEY_KP_COMMA LITERAL1 142 | PS2_KEY_F1 LITERAL1 143 | PS2_KEY_F2 LITERAL1 144 | PS2_KEY_F3 LITERAL1 145 | PS2_KEY_F4 LITERAL1 146 | PS2_KEY_F5 LITERAL1 147 | PS2_KEY_F6 LITERAL1 148 | PS2_KEY_F7 LITERAL1 149 | PS2_KEY_F8 LITERAL1 150 | PS2_KEY_F9 LITERAL1 151 | PS2_KEY_F10 LITERAL1 152 | PS2_KEY_F11 LITERAL1 153 | PS2_KEY_F12 LITERAL1 154 | PS2_KEY_F13 LITERAL1 155 | PS2_KEY_F14 LITERAL1 156 | PS2_KEY_F15 LITERAL1 157 | PS2_KEY_F16 LITERAL1 158 | PS2_KEY_F17 LITERAL1 159 | PS2_KEY_F18 LITERAL1 160 | PS2_KEY_F19 LITERAL1 161 | PS2_KEY_F20 LITERAL1 162 | PS2_KEY_F21 LITERAL1 163 | PS2_KEY_F22 LITERAL1 164 | PS2_KEY_F23 LITERAL1 165 | PS2_KEY_F24 LITERAL1 166 | PS2_KEY_NEXT_TR LITERAL1 167 | PS2_KEY_PREV_TR LITERAL1 168 | PS2_KEY_STOP LITERAL1 169 | PS2_KEY_PLAY LITERAL1 170 | PS2_KEY_MUTE LITERAL1 171 | PS2_KEY_VOL_UP LITERAL1 172 | PS2_KEY_VOL_DN LITERAL1 173 | PS2_KEY_MEDIA LITERAL1 174 | PS2_KEY_EMAIL LITERAL1 175 | PS2_KEY_CALC LITERAL1 176 | PS2_KEY_COMPUTER LITERAL1 177 | PS2_KEY_WEB_SEARCH LITERAL1 178 | PS2_KEY_WEB_HOME LITERAL1 179 | PS2_KEY_WEB_BACK LITERAL1 180 | PS2_KEY_WEB_FORWARD LITERAL1 181 | PS2_KEY_WEB_STOP LITERAL1 182 | PS2_KEY_WEB_REFRESH LITERAL1 183 | PS2_KEY_WEB_FAVOR LITERAL1 184 | PS2_KEY_POWER LITERAL1 185 | PS2_KEY_SLEEP LITERAL1 186 | PS2_KEY_WAKE LITERAL1 187 | PS2_KEY_INTL1 LITERAL1 188 | PS2_KEY_INTL2 LITERAL1 189 | PS2_KEY_INTL3 LITERAL1 190 | PS2_KEY_INTL4 LITERAL1 191 | PS2_KEY_INTL5 LITERAL1 192 | PS2_KEY_LANG1 LITERAL1 193 | PS2_KEY_LANG2 LITERAL1 194 | PS2_KEY_LANG3 LITERAL1 195 | PS2_KEY_LANG4 LITERAL1 196 | PS2_KEY_LANG5 LITERAL1 197 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=PS2KeyAdvanced 2 | version=1.0.9 3 | author=Paul Carpenter 4 | maintainer=Paul Carpenter 5 | sentence=PS2 keyboard FULL control and ALL keys processing, as well as LED control. 6 | paragraph=Provides ability to convert long key stroke code sequences to a single integer, for all keys ANY Latin keyboard, even multimedia and 24 Function key keyboards. Architectures AVR, SAM (Due), SAMD1, STM32 7 | category=Other 8 | url=https://github.com/techpaul/PS2KeyAdvanced.git 9 | architectures=avr,sam,samd1,stm32,esp32 10 | includes=PS2KeyAdvanced.h 11 | 12 | -------------------------------------------------------------------------------- /src/PS2KeyAdvanced.cpp: -------------------------------------------------------------------------------- 1 | /* Version V1.0.9 2 | PS2KeyAdvanced.cpp - PS2KeyAdvanced library 3 | Copyright (c) 2007 Free Software Foundation. All right reserved. 4 | Written by Paul Carpenter, PC Services 5 | Created September 2014 6 | Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management 7 | January 2020 Fix typos, correct keyboard reset status improve library.properties 8 | and additional platform handling and some documentation 9 | March 2020 Add SAMD1 as recognised support as has been tested by user 10 | Improve different architecture handling 11 | November 2020 Add support for STM32 from user Hiabuto-de 12 | Tested on STM32Duino-Framework and PlatformIO on STM32F103C8T6 and an IBM Model M 13 | July 2021 Add workaround for ESP32 issue with Silicon (hardware) from user submissions 14 | 15 | IMPORTANT WARNING 16 | 17 | If using a DUE or similar board with 3V3 I/O you MUST put a level translator 18 | like a Texas Instruments TXS0102 or FET circuit as the signals are 19 | Bi-directional (signals transmitted from both ends on same wire). 20 | 21 | Failure to do so may damage your Arduino Due or similar board. 22 | 23 | Test History 24 | September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 25 | January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board 26 | Manager V1.6.6 27 | 28 | 29 | Assumption - Only ONE keyboard added to one Arduino 30 | - No stream support 31 | 32 | This is for a LATIN style keyboard using Scan code set 2. See various 33 | websites on what different scan code sets use. Scan Code Set 2 is the 34 | default scan code set for PS2 keyboards on power up. 35 | 36 | Fully featured PS2 keyboard library to provide 37 | All keys as a keycode (A-Z and 0-9 as ASCII equivalents) 38 | All function and movement keys supported even multi-lingual 39 | Parity checking of data sent/received on receive request keyboard resend 40 | Resends data when needed handles keyboard protocol for RESEND and ECHO 41 | Functions for get and set of 42 | Scancode set in use READ only 43 | LED and LOCK control 44 | ReadID 45 | Reset keyboard 46 | Send ECHO 47 | Handles NUM, _CAPS and SCROLL lock keys to LEDs 48 | Handles NUM/SCROLL internally 49 | 50 | Returns an uint16_t containing 51 | Make/Break status 52 | CAPS status 53 | SHIFT, CTRL, ALT, ALT GR, GUI keys 54 | Flag for function key not a displayable/printable character 55 | 8 bit key code 56 | 57 | Code Ranges(bottom byte of uint16_t) see PS2KeyAdvanced.h for details 58 | 0 invalid/error 59 | 1-1F Functions (_CAPS, _SHIFT, _ALT, Enter, DEL... ) 60 | 1A-1F Functions with ASCII control code 61 | (DEL, BS, TAB, ESC, ENTER, SPACE) 62 | 20-60 Printable characters noting 63 | 0-9 = 0x30 to 0x39 as ASCII 64 | A to Z = 0x41 to 0x5A as upper case ASCII type codes 65 | 8B Extra European key 66 | 61-A0 Function keys and other special keys (plus F2 and F1 less 8B) 67 | 61-78 F1 to F24 68 | 79-8A Multimedia 69 | 8C-8E ACPI power 70 | 91-A0 and F2 and F1 - Special multilingual 71 | A8-FF Keyboard communications commands (note F2 and F1 are special 72 | codes for special multi-lingual keyboards) 73 | 74 | By using these ranges it is possible to perform detection of any key and do 75 | easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code. 76 | 77 | Top Byte is 8 bits denoting as follows with defines for bit code 78 | 79 | Define name bit description 80 | PS2_BREAK 15 1 = Break key code 81 | (MSB) 0 = Make Key code 82 | PS2_SHIFT 14 1 = Shift key pressed as well (either side) 83 | 0 = NO shift key 84 | PS2_CTRL 13 1 = Ctrl key pressed as well (either side) 85 | 0 = NO Ctrl key 86 | PS2_CAPS 12 1 = Caps Lock ON 87 | 0 = Caps lock OFF 88 | PS2_ALT 11 1 = Left Alt key pressed as well 89 | 0 = NO Left Alt key 90 | PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well 91 | 0 = NO Right Alt key 92 | PS2_GUI 9 1 = GUI key pressed as well (either) 93 | 0 = NO GUI key 94 | PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter) 95 | 0 = standard character key 96 | 97 | Error Codes 98 | Most functions return 0 or 0xFFFF as error, other codes to note and 99 | handle appropriately value in bottom byte 100 | 0xAA keyboard has reset and passed power up tests 101 | will happen if keyboard plugged in after code start 102 | 0xFC Keyboard General error or power up fail 103 | 104 | It is responsibility of your programme to deal with converting special cases 105 | like <_CTRL>+ sends a special code to something else. A better method 106 | is to use PS2KeyMap library and add your own table to that library. If you 107 | wish to do that make a NEW library called SOMETHING different NOT a variant 108 | or revision of this one, as you are changing base functionality 109 | 110 | See PS2KeyCode.h for codes from the keyboard this library uses to decode. 111 | (may disappear in updates do not rely on this file or definitions) 112 | 113 | See PS2KeyAvanced.h for returned definitions of Keys and accessible 114 | definitions 115 | 116 | See PS2KeyMap.h for tables currently supported 117 | 118 | To get the key as ASCII/UTF-8 single byte character conversion requires use 119 | of PS2KeyMap library AS WELL. 120 | 121 | This library is free software; you can redistribute it and/or 122 | modify it under the terms of the GNU Lesser General Public 123 | License as published by the Free Software Foundation; either 124 | version 2.1 of the License, or (at your option) any later version. 125 | 126 | This library is distributed in the hope that it will be useful, 127 | but WITHOUT ANY WARRANTY; without even the implied warranty of 128 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 129 | Lesser General Public License for more details. 130 | 131 | You should have received a copy of the GNU Lesser General Public 132 | License along with this library; if not, write to the Free Software 133 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 134 | */ 135 | #include 136 | // Internal headers for library defines/codes/etc 137 | #include "PS2KeyAdvanced.h" 138 | #include "PS2KeyCode.h" 139 | #include "PS2KeyTable.h" 140 | 141 | 142 | // Private function declarations 143 | void send_bit( void ); 144 | void send_now( uint8_t ); 145 | int16_t send_next( void ); 146 | void ps2_reset( void ); 147 | uint8_t decode_key( uint8_t ); 148 | void pininput( uint8_t ); 149 | void set_lock( ); 150 | 151 | /* Constant control functions to flags array 152 | in translated key code value order */ 153 | #if defined( PS2_REQUIRES_PROGMEM ) 154 | const uint8_t PROGMEM control_flags[] = { 155 | #else 156 | const uint8_t control_flags[] = { 157 | #endif 158 | _SHIFT, _SHIFT, _CTRL, _CTRL, 159 | _ALT, _ALT_GR, _GUI, _GUI 160 | }; 161 | 162 | // Private Variables 163 | volatile uint8_t _ps2mode; /* _ps2mode contains 164 | _PS2_BUSY bit 7 = busy until all expected bytes RX/TX 165 | _TX_MODE bit 6 = direction 1 = TX, 0 = RX (default) 166 | _BREAK_KEY bit 5 = break code detected 167 | _WAIT_RESPONSE bit 4 = expecting data response 168 | _E0_MODE bit 3 = in E0 mode 169 | _E1_MODE bit 2 = in E1 mode 170 | _LAST_VALID bit 1 = last sent valid in case we receive resend 171 | and not sent anything */ 172 | 173 | /* volatile RX buffers and variables accessed via interrupt functions */ 174 | volatile uint16_t _rx_buffer[ _RX_BUFFER_SIZE ]; // buffer for data from keyboard 175 | volatile uint8_t _head; // _head = last byte written 176 | uint8_t _tail; // _tail = last byte read (not modified in IRQ ever) 177 | volatile int8_t _bytes_expected; 178 | volatile uint8_t _bitcount; // Main state variable and bit count for interrupts 179 | volatile uint8_t _shiftdata; 180 | volatile uint8_t _parity; 181 | 182 | /* TX variables */ 183 | volatile uint8_t _tx_buff[ _TX_BUFFER_SIZE ]; // buffer for keyboard commands 184 | volatile uint8_t _tx_head; // buffer write pointer 185 | volatile uint8_t _tx_tail; // buffer read pointer 186 | volatile uint8_t _last_sent; // last byte if resend requested 187 | volatile uint8_t _now_send; // immediate byte to send 188 | volatile uint8_t _response_count; // bytes expected in reply to next TX 189 | volatile uint8_t _tx_ready; // TX status for type of send contains 190 | /* _HANDSHAKE 0x80 = handshaking command (ECHO/RESEND) 191 | _COMMAND 0x01 = other command processing */ 192 | 193 | /* Output key buffering */ 194 | uint16_t _key_buffer[ _KEY_BUFF_SIZE ]; // Output Buffer for translated keys 195 | uint8_t _key_head; // Output buffer WR pointer 196 | uint8_t _key_tail; // Output buffer RD pointer 197 | uint8_t _mode = 0; // Mode for output buffer contains 198 | /* _NO_REPEATS 0x80 No repeat make codes for _CTRL, _ALT, _SHIFT, _GUI 199 | _NO_BREAKS 0x08 No break codes */ 200 | 201 | // Arduino settings for pins and interrupts Needed to send data 202 | uint8_t PS2_DataPin; 203 | uint8_t PS2_IrqPin; 204 | 205 | // Key decoding variables 206 | uint8_t PS2_led_lock = 0; // LED and Lock status 207 | uint8_t PS2_lockstate[ 4 ]; // Save if had break on key for locks 208 | uint8_t PS2_keystatus; // current CAPS etc status for top byte 209 | 210 | 211 | /*------------------ Code starts here -------------------------*/ 212 | 213 | /* The ISR for the external interrupt 214 | To receive 11 bits - start 8 data, ODD parity, stop 215 | To send data calls send_bit( ) 216 | Interrupt every falling incoming clock edge from keyboard */ 217 | void ps2interrupt( void ) 218 | { 219 | // Workaround for ESP32 SILICON error see extra/Porting.md 220 | #ifdef PS2_ONLY_CHANGE_IRQ 221 | if( digitalRead( PS2_IrqPin ) ) 222 | return; 223 | #endif 224 | if( _ps2mode & _TX_MODE ) 225 | send_bit( ); 226 | else 227 | { 228 | static uint32_t prev_ms = 0; 229 | uint32_t now_ms; 230 | uint8_t val, ret; 231 | 232 | val = digitalRead( PS2_DataPin ); 233 | /* timeout catch for glitches reset everything */ 234 | now_ms = millis( ); 235 | if( now_ms - prev_ms > 250 ) 236 | { 237 | _bitcount = 0; 238 | _shiftdata = 0; 239 | } 240 | prev_ms = now_ms; 241 | _bitcount++; // Now point to next bit 242 | switch( _bitcount ) 243 | { 244 | case 1: // Start bit 245 | _parity = 0; 246 | _ps2mode |= _PS2_BUSY; // set busy 247 | break; 248 | case 2: 249 | case 3: 250 | case 4: 251 | case 5: 252 | case 6: 253 | case 7: 254 | case 8: 255 | case 9: // Data bits 256 | _parity += val; // another one received ? 257 | _shiftdata >>= 1; // right _SHIFT one place for next bit 258 | _shiftdata |= ( val ) ? 0x80 : 0; // or in MSbit 259 | break; 260 | case 10: // Parity check 261 | _parity &= 1; // Get LSB if 1 = odd number of 1's so parity bit should be 0 262 | if( _parity == val ) // Both same parity error 263 | _parity = 0xFD; // To ensure at next bit count clear and discard 264 | break; 265 | case 11: // Stop bit lots of spare time now 266 | if( _parity >= 0xFD ) // had parity error 267 | { 268 | send_now( PS2_KC_RESEND ); // request resend 269 | _tx_ready |= _HANDSHAKE; 270 | } 271 | else // Good so save byte in _rx_buffer 272 | { 273 | // Check _SHIFTed data for commands and action 274 | ret = decode_key( _shiftdata ); 275 | if( ret & 0x2 ) // decrement expected bytes 276 | _bytes_expected--; 277 | if( _bytes_expected <= 0 || ret & 4 ) // Save value ?? 278 | { 279 | val = _head + 1; 280 | if( val >= _RX_BUFFER_SIZE ) 281 | val = 0; 282 | if( val != _tail ) 283 | { 284 | // get last byte to save 285 | _rx_buffer[ val ] = uint16_t( _shiftdata ); 286 | // save extra details 287 | _rx_buffer[ val ] |= uint16_t( _ps2mode ) << 8; 288 | _head = val; 289 | } 290 | } 291 | if( ret & 0x10 ) // Special command to send (ECHO/RESEND) 292 | { 293 | send_now( _now_send ); 294 | _tx_ready |= _HANDSHAKE; 295 | } 296 | else 297 | if( _bytes_expected <= 0 ) // Receive data finished 298 | { 299 | // Set mode and status for next receive byte 300 | _ps2mode &= ~( _E0_MODE + _E1_MODE + _WAIT_RESPONSE + _BREAK_KEY ); 301 | _bytes_expected = 0; 302 | _ps2mode &= ~_PS2_BUSY; 303 | send_next( ); // Check for more to send 304 | } 305 | } 306 | _bitcount = 0; // end of byte 307 | break; 308 | default: // in case of weird error and end of byte reception re-sync 309 | _bitcount = 0; 310 | } 311 | } 312 | } 313 | 314 | 315 | /* Decode value received to check for errors commands and responses 316 | NOT keycode translate yet 317 | returns bit Or'ing 318 | 0x10 send command in _now_send (after any saves and decrements) 319 | 0x08 error abort reception and reset status and queues 320 | 0x04 save value ( complete after translation ) 321 | 0x02 decrement count of bytes to expected 322 | 323 | Codes like EE, AA and FC ( Echo, BAT pass and fail) treated as valid codes 324 | return code 6 325 | */ 326 | uint8_t decode_key( uint8_t value ) 327 | { 328 | uint8_t state; 329 | 330 | state = 6; // default state save and decrement 331 | 332 | // Anything but resend received clear valid value to resend 333 | if( value != PS2_KC_RESEND ) 334 | _ps2mode &= ~( _LAST_VALID ); 335 | 336 | // First check not a valid response code from a host command 337 | if( _ps2mode & _WAIT_RESPONSE ) 338 | if( value < 0xF0 ) 339 | return state; // Save response and decrement 340 | 341 | // E1 Pause mode special case just decrement 342 | if( _ps2mode & _E1_MODE ) 343 | return 2; 344 | 345 | switch( value ) 346 | { 347 | case 0: // Buffer overrun Errors Reset modes and buffers 348 | case PS2_KC_OVERRUN: 349 | ps2_reset( ); 350 | state = 0xC; 351 | break; 352 | case PS2_KC_RESEND: // Resend last byte if we have sent something 353 | if( ( _ps2mode & _LAST_VALID ) ) 354 | { 355 | _now_send = _last_sent; 356 | state = 0x10; 357 | } 358 | else 359 | state = 0; 360 | break; 361 | case PS2_KC_ERROR: // General error pass up but stop any sending or receiving 362 | _bytes_expected = 0; 363 | _ps2mode = 0; 364 | _tx_ready = 0; 365 | state = 0xE; 366 | break; 367 | case PS2_KC_KEYBREAK: // break Code - wait the final key byte 368 | _bytes_expected = 1; 369 | _ps2mode |= _BREAK_KEY; 370 | state = 0; 371 | break; 372 | case PS2_KC_ECHO: // Echo if we did not originate echo back 373 | state = 4; // always save 374 | if( _ps2mode & _LAST_VALID && _last_sent != PS2_KC_ECHO ) 375 | { 376 | _now_send = PS2_KC_ECHO; 377 | state |= 0x10; // send _command on exit 378 | } 379 | break; 380 | case PS2_KC_BAT: // BAT pass 381 | _bytes_expected = 0; // reset as if in middle of something lost now 382 | state = 4; 383 | break; 384 | case PS2_KC_EXTEND1: // Major extend code (PAUSE key only) 385 | if( !( _ps2mode & _E1_MODE ) ) // First E1 only 386 | { 387 | _bytes_expected = 7; // seven more bytes 388 | _ps2mode |= _E1_MODE; 389 | _ps2mode &= ~_BREAK_KEY; // Always a make 390 | } 391 | state = 0; 392 | break; 393 | case PS2_KC_EXTEND: // Two byte Extend code 394 | _bytes_expected = 1; // one more byte at least to wait for 395 | _ps2mode |= _E0_MODE; 396 | state = 0; 397 | break; 398 | } 399 | return state; 400 | } 401 | 402 | 403 | /* Send data to keyboard 404 | Data pin direction should already be changed 405 | Start bit would be already set so each clock setup for next clock 406 | parity and _bitcount should be 0 already and busy should be set 407 | 408 | Start bit setting is due to bug in attachinterrupt not clearing pending interrupts 409 | Also no clear pending interrupt function */ 410 | void send_bit( void ) 411 | { 412 | uint8_t val; 413 | 414 | _bitcount++; // Now point to next bit 415 | switch( _bitcount ) 416 | { 417 | case 1: 418 | #if defined( PS2_CLEAR_PENDING_IRQ ) 419 | // Start bit due to Arduino bug 420 | digitalWrite( PS2_DataPin, LOW ); 421 | break; 422 | #endif 423 | case 2: 424 | case 3: 425 | case 4: 426 | case 5: 427 | case 6: 428 | case 7: 429 | case 8: 430 | case 9: 431 | // Data bits 432 | val = _shiftdata & 0x01; // get LSB 433 | digitalWrite( PS2_DataPin, val ); // send start bit 434 | _parity += val; // another one received ? 435 | _shiftdata >>= 1; // right _SHIFT one place for next bit 436 | break; 437 | case 10: 438 | // Parity - Send LSB if 1 = odd number of 1's so parity should be 0 439 | digitalWrite( PS2_DataPin, ( ~_parity & 1 ) ); 440 | break; 441 | case 11: // Stop bit write change to input pull up for high stop bit 442 | pininput( PS2_DataPin ); 443 | break; 444 | case 12: // Acknowledge bit low we cannot do anything if high instead of low 445 | if( !( _now_send == PS2_KC_ECHO || _now_send == PS2_KC_RESEND ) ) 446 | { 447 | _last_sent = _now_send; // save in case of resend request 448 | _ps2mode |= _LAST_VALID; 449 | } 450 | // clear modes to receive again 451 | _ps2mode &= ~_TX_MODE; 452 | if( _tx_ready & _HANDSHAKE ) // If _HANDSHAKE done 453 | _tx_ready &= ~_HANDSHAKE; 454 | else // else we finished a command 455 | _tx_ready &= ~_COMMAND; 456 | if( !( _ps2mode & _WAIT_RESPONSE ) ) // if not wait response 457 | send_next( ); // check anything else to queue up 458 | _bitcount = 0; // end of byte 459 | break; 460 | default: // in case of weird error and end of byte reception re-sync 461 | _bitcount = 0; 462 | } 463 | } 464 | 465 | 466 | /* Takes a byte sets up variables and starts the data sending processes 467 | Starts the actual byte transmission 468 | calling code must make sure line is idle and able to send 469 | Whilst this function adds long delays the process of the delays 470 | will STOP the interrupt source (keyboard) externally when clock held low 471 | _tx_ready contains 2 flags checked in this order 472 | _HANDSHAKE command sent as part of receiving e.g. ECHO, RESEND 473 | _COMMAND other commands not part of receiving 474 | Main difference _bytes_expected is NOT altered in _HANDSHAKE mode 475 | in command mode we update _bytes_expected with number of response bytes 476 | */ 477 | void send_now( uint8_t command ) 478 | { 479 | _shiftdata = command; 480 | _now_send = command; // copy for later to save in last sent 481 | #if defined( PS2_CLEAR_PENDING_IRQ ) 482 | _bitcount = 0; // AVR/SAM ignore extra interrupt 483 | #else 484 | _bitcount = 1; // Normal processors 485 | #endif 486 | _parity = 0; 487 | _ps2mode |= _TX_MODE + _PS2_BUSY; 488 | 489 | // Only do this if sending a command not from Handshaking 490 | if( !( _tx_ready & _HANDSHAKE ) && ( _tx_ready & _COMMAND ) ) 491 | { 492 | _bytes_expected = _response_count; // How many bytes command will generate 493 | _ps2mode |= _WAIT_RESPONSE; 494 | } 495 | 496 | // STOP interrupt handler 497 | // Setting pin output low will cause interrupt before ready 498 | detachInterrupt( digitalPinToInterrupt( PS2_IrqPin ) ); 499 | // set pins to outputs and high 500 | digitalWrite( PS2_DataPin, HIGH ); 501 | pinMode( PS2_DataPin, OUTPUT ); 502 | digitalWrite( PS2_IrqPin, HIGH ); 503 | pinMode( PS2_IrqPin, OUTPUT ); 504 | // Essential for PS2 spec compliance 505 | delayMicroseconds( 10 ); 506 | // set Clock LOW 507 | digitalWrite( PS2_IrqPin, LOW ); 508 | // Essential for PS2 spec compliance 509 | // set clock low for 60us 510 | delayMicroseconds( 60 ); 511 | // Set data low - Start bit 512 | digitalWrite( PS2_DataPin, LOW ); 513 | // set clock to input_pullup data stays output while writing to keyboard 514 | pininput( PS2_IrqPin ); 515 | // Restart interrupt handler 516 | attachInterrupt( digitalPinToInterrupt( PS2_IrqPin ), ps2interrupt, FALLING ); 517 | // wait clock interrupt to send data 518 | } 519 | 520 | 521 | /* Send next byte/command from TX queue and start sending 522 | Must be ready to send and idle 523 | Assumes commands consist of 1 or more bytes and wait for response then may or 524 | not be followed by further bytes to send with or without response 525 | Checks 526 | 1/ Buffer empty return empty buffer 527 | 2/ Busy return busy (will be checked by interrupt routines later) 528 | 3/ Read next byte (next byte to send) 529 | 4/ Check if following byte(s) are command/data or response 530 | 531 | Returns 1 if started transmission or queued 532 | -134 if already busy 533 | -2 if buffer empty 534 | 535 | Note PS2_KEY_IGNORE is used to denote a byte(s) expected in response */ 536 | int16_t send_next( void ) 537 | { 538 | uint8_t i; 539 | int16_t val; 540 | 541 | val = -1; 542 | // Check buffer not empty 543 | i = _tx_tail; 544 | if( i == _tx_head ) 545 | return -2; 546 | 547 | // set command bit in _tx_ready as another command to do 548 | _tx_ready |= _COMMAND; 549 | 550 | // Already item waiting to be sent or sending interrupt routines will call back 551 | if( _tx_ready & _HANDSHAKE ) 552 | return -134; 553 | 554 | // if busy let interrupt catch and call us again 555 | if( _ps2mode & _PS2_BUSY ) 556 | return -134; 557 | 558 | // Following only accessed when not receiving or sending protocol bytes 559 | // Scan for command response and expected bytes to follow 560 | _response_count = 0; 561 | do 562 | { 563 | i++; 564 | if( i >= _TX_BUFFER_SIZE ) 565 | i = 0; 566 | if( val == -1 ) 567 | val = _tx_buff[ i ]; 568 | else 569 | if( _tx_buff[ i ] != PS2_KEY_IGNORE ) 570 | break; 571 | else 572 | _response_count++; 573 | _tx_tail = i; 574 | } 575 | while( i != _tx_head ); 576 | // Now know what to send and expect start the actual wire sending 577 | send_now( val ); 578 | return 1; 579 | } 580 | 581 | 582 | /* Send a byte to the TX buffer 583 | Value in buffer of PS2_KEY_IGNORE signifies wait for response, 584 | use one for each byte expected 585 | 586 | Returns -4 - if buffer full (buffer overrun not written) 587 | Returns 1 byte written when done */ 588 | int send_byte( uint8_t val ) 589 | { 590 | uint8_t ret; 591 | 592 | ret = _tx_head + 1; 593 | if( ret >= _TX_BUFFER_SIZE ) 594 | ret = 0; 595 | if( ret != _tx_tail ) 596 | { 597 | _tx_buff[ ret ] = val; 598 | _tx_head = ret; 599 | return 1; 600 | } 601 | return -4; 602 | } 603 | 604 | 605 | // initialize a data pin for input 606 | void pininput( uint8_t pin ) 607 | { 608 | #ifdef INPUT_PULLUP 609 | pinMode( pin, INPUT_PULLUP ); 610 | #else 611 | digitalWrite( pin, HIGH ); 612 | pinMode( pin, INPUT ); 613 | #endif 614 | } 615 | 616 | 617 | void ps2_reset( void ) 618 | { 619 | /* reset buffers and states */ 620 | _tx_head = 0; 621 | _tx_tail = 0; 622 | _tx_ready = 0; 623 | _response_count = 0; 624 | _head = 0; 625 | _tail = 0; 626 | _bitcount = 0; 627 | PS2_keystatus = 0; 628 | PS2_led_lock = 0; 629 | _ps2mode = 0; 630 | } 631 | 632 | 633 | uint8_t key_available( ) 634 | { 635 | int8_t i; 636 | 637 | i = _head - _tail; 638 | if( i < 0 ) 639 | i += _RX_BUFFER_SIZE; 640 | return uint8_t( i ); 641 | } 642 | 643 | 644 | /* Translate PS2 keyboard code sequence into our key code data 645 | PAUSE key (_E1_MODE) is de_ALT with as special case, and 646 | command responses not translated 647 | 648 | Called from read function as too long for in interrupt 649 | 650 | Returns 0 for no valid key or processed internally ignored or similar 651 | 0 for empty buffer 652 | */ 653 | uint16_t translate( void ) 654 | { 655 | uint8_t index, length, data; 656 | uint16_t retdata; 657 | 658 | // get next character 659 | // Check first something to fetch 660 | index = _tail; 661 | // check for empty buffer 662 | if( index == _head ) 663 | return 0; 664 | index++; 665 | if( index >= _RX_BUFFER_SIZE ) 666 | index = 0; 667 | _tail = index; 668 | // Get the flags byte break modes etc in this order 669 | data = _rx_buffer[ index ] & 0xFF; 670 | index = ( _rx_buffer[ index ] & 0xFF00 ) >> 8; 671 | 672 | // Catch special case of PAUSE key 673 | if( index & _E1_MODE ) 674 | return PS2_KEY_PAUSE + _FUNCTION; 675 | 676 | // Ignore anything not actual keycode but command/response 677 | // Return untranslated as valid 678 | if( ( data >= PS2_KC_BAT && data != PS2_KC_LANG1 && data != PS2_KC_LANG2 ) 679 | || ( index & _WAIT_RESPONSE ) ) 680 | return ( uint16_t )data; 681 | 682 | // Gather the break of key status 683 | if( index & _BREAK_KEY ) 684 | PS2_keystatus |= _BREAK; 685 | else 686 | PS2_keystatus &= ~_BREAK; 687 | 688 | retdata = 0; // error code by default 689 | // Scan appropriate table 690 | if( index & _E0_MODE ) 691 | { 692 | length = sizeof( extended_key ) / sizeof( extended_key[ 0 ] ); 693 | for( index = 0; index < length; index++ ) 694 | #if defined( PS2_REQUIRES_PROGMEM ) 695 | if( data == pgm_read_byte( &extended_key[ index ][ 0 ] ) ) 696 | { 697 | retdata = pgm_read_byte( &extended_key[ index ][ 1 ] ); 698 | #else 699 | if( data == extended_key[ index ][ 0 ] ) 700 | { 701 | retdata = extended_key[ index ][ 1 ]; 702 | #endif 703 | break; 704 | } 705 | } 706 | else 707 | { 708 | length = sizeof( single_key ) / sizeof( single_key[ 0 ] ); 709 | for( index = 0; index < length; index++ ) 710 | #if defined( PS2_REQUIRES_PROGMEM ) 711 | if( data == pgm_read_byte( &single_key[ index ][ 0 ] ) ) 712 | { 713 | retdata = pgm_read_byte( &single_key[ index ][ 1 ] ); 714 | #else 715 | if( data == single_key[ index ][ 0 ] ) 716 | { 717 | retdata = single_key[ index ][ 1 ]; 718 | #endif 719 | break; 720 | } 721 | } 722 | // trap not found key 723 | if( index == length ) 724 | retdata = 0; 725 | /* valid found values only */ 726 | if( retdata > 0 ) 727 | { 728 | if( retdata <= PS2_KEY_CAPS ) 729 | { // process lock keys need second make to turn off 730 | if( PS2_keystatus & _BREAK ) 731 | { 732 | PS2_lockstate[ retdata ] = 0; // Set received a break so next make toggles LOCK status 733 | retdata = PS2_KEY_IGNORE; // ignore key 734 | } 735 | else 736 | { 737 | if( PS2_lockstate[ retdata ] == 1 ) 738 | retdata = PS2_KEY_IGNORE; // ignore key if make and not received break 739 | else 740 | { 741 | PS2_lockstate[ retdata ] = 1; 742 | switch( retdata ) 743 | { 744 | case PS2_KEY_CAPS: index = PS2_LOCK_CAPS; 745 | // Set CAPS lock if not set before 746 | if( PS2_keystatus & _CAPS ) 747 | PS2_keystatus &= ~_CAPS; 748 | else 749 | PS2_keystatus |= _CAPS; 750 | break; 751 | case PS2_KEY_SCROLL: index = PS2_LOCK_SCROLL; 752 | break; 753 | case PS2_KEY_NUM: index = PS2_LOCK_NUM; 754 | break; 755 | } 756 | // Now update PS2_led_lock status to match 757 | if( PS2_led_lock & index ) 758 | { 759 | PS2_led_lock &= ~index; 760 | PS2_keystatus |= _BREAK; // send as break 761 | } 762 | else 763 | PS2_led_lock |= index; 764 | set_lock( ); 765 | } 766 | } 767 | } 768 | else 769 | if( retdata >= PS2_KEY_L_SHIFT && retdata <= PS2_KEY_R_GUI ) 770 | { // Update bits for _SHIFT, _CTRL, _ALT, _ALT GR, _GUI in status 771 | #if defined( PS2_REQUIRES_PROGMEM ) 772 | index = pgm_read_byte( &control_flags[ retdata - PS2_KEY_L_SHIFT ] ); 773 | #else 774 | index = control_flags[ retdata - PS2_KEY_L_SHIFT ]; 775 | #endif 776 | if( PS2_keystatus & _BREAK ) 777 | PS2_keystatus &= ~index; 778 | else 779 | // if already set ignore repeats if flag set 780 | if( ( PS2_keystatus & index ) && ( _mode & _NO_REPEATS ) ) 781 | retdata = PS2_KEY_IGNORE; // ignore repeat _SHIFT, _CTRL, _ALT, _GUI 782 | else 783 | PS2_keystatus |= index; 784 | } 785 | else 786 | // Numeric keypad ONLY works in numlock state or when _SHIFT status 787 | if( retdata >= PS2_KEY_KP0 && retdata <= PS2_KEY_KP_DOT ) 788 | if( !( PS2_led_lock & PS2_LOCK_NUM ) || ( PS2_keystatus & _SHIFT ) ) 789 | #if defined( PS2_REQUIRES_PROGMEM ) 790 | retdata = pgm_read_byte( &scroll_remap[ retdata - PS2_KEY_KP0 ] ); 791 | #else 792 | retdata = scroll_remap[ retdata - PS2_KEY_KP0 ]; 793 | #endif 794 | // Sort break code handling or ignore for all having processed the _SHIFT etc status 795 | if( ( PS2_keystatus & _BREAK ) && ( _mode & _NO_BREAKS ) ) 796 | return ( uint16_t )PS2_KEY_IGNORE; 797 | // Assign Function keys _mode 798 | if( ( retdata <= PS2_KEY_SPACE || retdata >= PS2_KEY_F1 ) && retdata != PS2_KEY_EUROPE2 ) 799 | PS2_keystatus |= _FUNCTION; 800 | else 801 | PS2_keystatus &= ~_FUNCTION; 802 | } 803 | return ( retdata | ( (uint16_t)PS2_keystatus << 8 ) ); 804 | } 805 | 806 | 807 | /* Build command to send lock status 808 | Assumes data is within range */ 809 | void set_lock( ) 810 | { 811 | send_byte( PS2_KC_LOCK ); // send command 812 | send_byte( PS2_KEY_IGNORE ); // wait ACK 813 | send_byte( PS2_led_lock ); // send data from internal variable 814 | if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait ACK 815 | send_next( ); // if idle start transmission 816 | } 817 | 818 | 819 | /* Send echo command to keyboard 820 | returned data in keyboard buffer read as keys */ 821 | void PS2KeyAdvanced::echo( void ) 822 | { 823 | send_byte( PS2_KC_ECHO ); // send command 824 | if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data PS2_KC_ECHO 825 | send_next( ); // if idle start transmission 826 | } 827 | 828 | 829 | /* Get the ID used in keyboard 830 | returned data in keyboard buffer read as keys */ 831 | void PS2KeyAdvanced::readID( void ) 832 | { 833 | send_byte( PS2_KC_READID ); // send command 834 | send_byte( PS2_KEY_IGNORE ); // wait ACK 835 | send_byte( PS2_KEY_IGNORE ); // wait data 836 | if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data 837 | send_next( ); // if idle start transmission 838 | } 839 | 840 | 841 | /* Get the current Scancode Set used in keyboard 842 | returned data in keyboard buffer read as keys */ 843 | void PS2KeyAdvanced::getScanCodeSet( void ) 844 | { 845 | send_byte( PS2_KC_SCANCODE ); // send command 846 | send_byte( PS2_KEY_IGNORE ); // wait ACK 847 | send_byte( 0 ); // send data 0 = read 848 | send_byte( PS2_KEY_IGNORE ); // wait ACK 849 | if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data 850 | send_next( ); // if idle start transmission 851 | } 852 | 853 | 854 | /* Returns the current status of Locks */ 855 | uint8_t PS2KeyAdvanced::getLock( ) 856 | { 857 | return( PS2_led_lock ); 858 | } 859 | 860 | 861 | /* Sets the current status of Locks and LEDs */ 862 | void PS2KeyAdvanced::setLock( uint8_t code ) 863 | { 864 | code &= 0xF; // To allow for rare keyboards with extra LED 865 | PS2_led_lock = code; // update our lock copy 866 | PS2_keystatus &= ~_CAPS; // Update copy of _CAPS lock as well 867 | PS2_keystatus |= ( code & PS2_LOCK_CAPS ) ? _CAPS : 0; 868 | set_lock( ); 869 | } 870 | 871 | 872 | /* Set library to not send break key codes 873 | 1 = no break codes 874 | 0 = send break codes */ 875 | void PS2KeyAdvanced::setNoBreak( uint8_t data ) 876 | { 877 | _mode &= ~_NO_BREAKS; 878 | _mode |= data ? _NO_BREAKS : 0; 879 | } 880 | 881 | /* Set library to not repeat make codes for _CTRL, _ALT, _GUI, _SHIFT 882 | 1 = no repeat codes 883 | 0 = send repeat codes */ 884 | void PS2KeyAdvanced::setNoRepeat( uint8_t data ) 885 | { 886 | _mode &= ~_NO_REPEATS; 887 | _mode |= data ? _NO_REPEATS : 0; 888 | } 889 | 890 | 891 | /* Resets keyboard when reset has completed 892 | keyboard sends AA - Pass or FC for fail */ 893 | void PS2KeyAdvanced::resetKey( ) 894 | { 895 | send_byte( PS2_KC_RESET ); // send command 896 | send_byte( PS2_KEY_IGNORE ); // wait ACK 897 | if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait data PS2_KC_BAT or PS2_KC_ERROR 898 | send_next( ); // if idle start transmission 899 | // LEDs and KeyStatus Reset too... to match keyboard 900 | PS2_led_lock = 0; 901 | PS2_keystatus = 0; 902 | } 903 | 904 | 905 | /* Send Typematic rate/delay command to keyboard 906 | First Parameter rate is 0 - 0x1F (31) 907 | 0 = 30 CPS 908 | 0x1F = 2 CPS 909 | default in keyboard is 0xB (10.9 CPS) 910 | Second Parameter delay is 0 - 3 for 0.25s to 1s in 0.25 increments 911 | default in keyboard is 1 = 0.5 second delay 912 | Returned data in keyboard buffer read as keys 913 | 914 | Error returns 0 OK 915 | -5 parameter error 916 | */ 917 | int PS2KeyAdvanced::typematic( uint8_t rate, uint8_t delay ) 918 | { 919 | if( rate > 31 || delay > 3 ) 920 | return -5; 921 | send_byte( PS2_KC_RATE ); // send command 922 | send_byte( PS2_KEY_IGNORE ); // wait ACK 923 | send_byte( ( delay << 5 ) + rate ); // Send values 924 | if( ( send_byte( PS2_KEY_IGNORE ) ) ) // wait ACK 925 | send_next( ); // if idle start transmission 926 | return 0; 927 | } 928 | 929 | 930 | /* Returns count of available processed key codes 931 | 932 | If processed key buffer (_key_buffer) buffer returns max count 933 | else processes input key code buffer until 934 | either input buffer empty 935 | or output buffer full 936 | returns actual count 937 | 938 | Returns 0 buffer empty 939 | 1 to buffer size less 1 as 1 to full buffer 940 | 941 | As with other ring buffers here when pointers match 942 | buffer empty so cannot actually hold buffer size values */ 943 | uint8_t PS2KeyAdvanced::available( ) 944 | { 945 | int8_t i, idx; 946 | uint16_t data; 947 | 948 | // check output queue 949 | i = _key_head - _key_tail; 950 | if( i < 0 ) 951 | i += _KEY_BUFF_SIZE; 952 | while( i < ( _KEY_BUFF_SIZE - 1 ) ) // process if not full 953 | if( key_available( ) ) // not check for more keys to process 954 | { 955 | data = translate( ); // get next translated key 956 | if( data == 0 ) // unless in buffer is empty 957 | break; 958 | if( ( data & 0xFF ) != PS2_KEY_IGNORE 959 | && ( data & 0xFF ) > 0 ) 960 | { 961 | idx = _key_head + 1; // point to next space 962 | if( idx >= _KEY_BUFF_SIZE ) // loop to front if necessary 963 | idx = 0; 964 | _key_buffer[ idx ] = data; // save the data to out buffer 965 | _key_head = idx; 966 | i++; // update count 967 | } 968 | } 969 | else 970 | break; // exit nothing coming in 971 | return uint8_t( i ); 972 | } 973 | 974 | 975 | /* read a decoded key from the keyboard buffer 976 | returns 0 for empty buffer */ 977 | uint16_t PS2KeyAdvanced::read( ) 978 | { 979 | uint16_t result; 980 | uint8_t idx; 981 | 982 | if( ( result = available( ) ) ) 983 | { 984 | idx = _key_tail; 985 | idx++; 986 | if( idx >= _KEY_BUFF_SIZE ) // loop to front if necessary 987 | idx = 0; 988 | _key_tail = idx; 989 | result = _key_buffer[ idx ]; 990 | } 991 | return result; 992 | } 993 | 994 | 995 | PS2KeyAdvanced::PS2KeyAdvanced( ) 996 | { 997 | // nothing to do here, begin( ) does it all 998 | } 999 | 1000 | 1001 | /* instantiate class for keyboard */ 1002 | void PS2KeyAdvanced::begin( uint8_t data_pin, uint8_t irq_pin ) 1003 | { 1004 | /* PS2 variables reset */ 1005 | ps2_reset( ); 1006 | 1007 | PS2_DataPin = data_pin; 1008 | PS2_IrqPin = irq_pin; 1009 | 1010 | // initialize the pins 1011 | pininput( PS2_IrqPin ); /* Setup Clock pin */ 1012 | pininput( PS2_DataPin ); /* Setup Data pin */ 1013 | 1014 | // Start interrupt handler 1015 | attachInterrupt( digitalPinToInterrupt( irq_pin ), ps2interrupt, FALLING ); 1016 | } 1017 | -------------------------------------------------------------------------------- /src/PS2KeyAdvanced.h: -------------------------------------------------------------------------------- 1 | /* Version V1.0.9 2 | PS2KeyAdvanced.h - PS2KeyAdvanced library 3 | Copyright (c) 2007 Free Software Foundation. All right reserved. 4 | Written by Paul Carpenter, PC Services 5 | Created September 2014 6 | Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management 7 | January 2020 Fix typos, correct keyboard reset status improve library.properties 8 | and additional platform handling and some documentation 9 | March 2020 Add SAMD1 as recognised support as has been tested by user 10 | Improve different architecture handling 11 | November 2020 Add support for STM32 from user Hiabuto-de 12 | Tested on STM32Duino-Framework and PlatformIO on STM32F103C8T6 and an IBM Model M 13 | July 2021 Add workaround for ESP32 issue with Silicon (hardware) from user submissions 14 | 15 | IMPORTANT WARNING 16 | 17 | If using a DUE or similar board with 3V3 I/O you MUST put a level translator 18 | like a Texas Instruments TXS0102 or FET circuit as the signals are 19 | Bi-directional (signals transmitted from both ends on same wire). 20 | 21 | Failure to do so may damage your Arduino Due or similar board. 22 | 23 | Test History 24 | September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 25 | January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board 26 | Manager V1.6.6 27 | 28 | ONLY use defines in this file others may disappear on updates. 29 | 30 | This is for a LATIN style keyboard using Scan code set 2. See various 31 | websites on what different scan code sets use. Scan Code Set 2 is the 32 | default scan code set for PS2 keyboards on power up. 33 | 34 | Will support most keyboards even ones with multimedia keys or even 24 function keys. 35 | 36 | Fully featured PS2 keyboard library to provide 37 | All function and movement keys supported even multi-lingual 38 | Parity checking of data sent/received on receive request keyboard resend 39 | Resends data when needed handles keyboard protocol for RESEND and ECHO 40 | Functions for get and set of 41 | Scancode set in use READ only 42 | LED and LOCK control 43 | ReadID 44 | Reset keyboard 45 | Send ECHO 46 | Ignore Break codes for keys 47 | Ignore typematic repeat of CTRL, SHIFT, ALT, Num, Scroll, Caps 48 | Handles NUM, CAPS and SCROLL lock keys to LEDs 49 | Handles NUM/SCROLL internally 50 | 51 | Read function Returns an UNSIGNED INT containing 52 | Make/Break status 53 | Caps status 54 | Shift, CTRL, ALT, ALT GR, GUI keys 55 | Flag for function key not a displayable/printable character 56 | 8 bit key code 57 | 58 | Code Ranges (bottom byte of unsigned int) 59 | 0 invalid/error 60 | 1-1F Functions (Caps, Shift, ALT, Enter, DEL... ) 61 | 1A-1F Functions with ASCII control code 62 | (DEL, BS, TAB, ESC, ENTER, SPACE) 63 | 20-61 Printable characters noting 64 | 0-9 = 0x30 to 0x39 as ASCII 65 | A to Z = 0x41 to 0x5A as upper case ASCII type codes 66 | 8B Extra European key 67 | 61-A0 Function keys and other special keys (plus F2 and F1) 68 | 61-78 F1 to F24 69 | 79-8A Multimedia 70 | 8B NOT included 71 | 8C-8E ACPI power 72 | 91-A0 and F2 and F1 - Special multilingual 73 | A8-FF Keyboard communications commands (note F2 and F1 are special 74 | codes for special multi-lingual keyboards) 75 | 76 | By using these ranges it is possible to perform detection of any key and do 77 | easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code. 78 | 79 | Top Byte is 8 bits denoting as follows with defines for bit code 80 | 81 | Define name bit description 82 | PS2_BREAK 15 1 = Break key code 83 | (MSB) 0 = Make Key code 84 | PS2_SHIFT 14 1 = Shift key pressed as well (either side) 85 | 0 = NO shift key 86 | PS2_CTRL 13 1 = Ctrl key pressed as well (either side) 87 | 0 = NO Ctrl key 88 | PS2_CAPS 12 1 = Caps Lock ON 89 | 0 = Caps lock OFF 90 | PS2_ALT 11 1 = Left Alt key pressed as well 91 | 0 = NO Left Alt key 92 | PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well 93 | 0 = NO Right Alt key 94 | PS2_GUI 9 1 = GUI key pressed as well (either) 95 | 0 = NO GUI key 96 | PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter) 97 | 0 = standard character key 98 | 99 | Error Codes 100 | Most functions return 0 or 0xFFFF as error, other codes to note and 101 | handle appropriately 102 | 0xAA keyboard has reset and passed power up tests 103 | will happen if keyboard plugged in after code start 104 | 0xFC Keyboard General error or power up fail 105 | 106 | It is responsibility of your programme to deal with converting special cases like 107 | + sends a special code to something else. If you wish to do that make a 108 | NEW library called SOMETHING different NOT a variant or revision of this one, as you 109 | are changing base functionality 110 | 111 | See PS2KeyCode.h for codes from the keyboard this library uses to decode. 112 | (may disappear in updates do not rely on that file or definitions) 113 | 114 | See this file for returned definitions of Keys 115 | 116 | Note defines starting 117 | PS2_KC_* are internal defines for codes from the keyboard 118 | PS2_KEY_* are the codes this library returns 119 | PS2_* remaining defines for use in higher levels 120 | 121 | To get the key as ASCII/UTF-8 single byte character conversion requires use 122 | of PS2KeyMap library AS WELL. 123 | 124 | This library is free software; you can redistribute it and/or 125 | modify it under the terms of the GNU Lesser General Public 126 | License as published by the Free Software Foundation; either 127 | version 2.1 of the License, or (at your option) any later version. 128 | 129 | This library is distributed in the hope that it will be useful, 130 | but WITHOUT ANY WARRANTY; without even the implied warranty of 131 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 132 | Lesser General Public License for more details. 133 | 134 | You should have received a copy of the GNU Lesser General Public 135 | License along with this library; if not, write to the Free Software 136 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 137 | */ 138 | #ifndef PS2KeyAdvanced_h 139 | #define PS2KeyAdvanced_h 140 | 141 | // Platform specific areas 142 | // Harvard architecture settings for PROGMEM 143 | // Add separate for EACH architecture as easier to maintain 144 | // AVR (includes Teensy 2.0) 145 | #if defined( ARDUINO_ARCH_AVR ) 146 | #define PS2_SUPPORTED 1 147 | #define PS2_REQUIRES_PROGMEM 1 148 | #define PS2_CLEAR_PENDING_IRQ 1 149 | #endif 150 | // SAM (Due) 151 | #if defined( ARDUINO_ARCH_SAM ) 152 | #define PS2_SUPPORTED 1 153 | #define PS2_CLEAR_PENDING_IRQ 1 154 | #endif 155 | // SAMD1 156 | #if defined( ARDUINO_ARCH_SAMD1 ) 157 | #define PS2_SUPPORTED 1 158 | #define PS2_CLEAR_PENDING_IRQ 1 159 | #endif 160 | // STM32 161 | #if defined( ARDUINO_ARCH_STM32 ) 162 | #define PS2_SUPPORTED 1 163 | #define PS2_CLEAR_PENDING_IRQ 1 164 | #endif 165 | // ESP32 166 | #if defined( ARDUINO_ARCH_ESP32 ) 167 | #define PS2_SUPPORTED 1 168 | #define PS2_ONLY_CHANGE_IRQ 1 169 | #endif 170 | 171 | // Invalid architecture 172 | #if !( defined( PS2_SUPPORTED ) ) 173 | #warning Library is NOT supported on this board Use at your OWN risk 174 | #endif 175 | 176 | /* Flags/bit masks for status bits in returned unsigned int value */ 177 | #define PS2_BREAK 0x8000 178 | #define PS2_SHIFT 0x4000 179 | #define PS2_CTRL 0x2000 180 | #define PS2_CAPS 0x1000 181 | #define PS2_ALT 0x800 182 | #define PS2_ALT_GR 0x400 183 | #define PS2_GUI 0x200 184 | #define PS2_FUNCTION 0x100 185 | 186 | /* General defines of communications codes */ 187 | /* Command or response */ 188 | #define PS2_KEY_RESEND 0xFE 189 | #define PS2_KEY_ACK 0xFA 190 | #define PS2_KEY_ECHO 0xEE 191 | /* Responses */ 192 | #define PS2_KEY_BAT 0xAA 193 | // Actually buffer overrun 194 | #define PS2_KEY_OVERRUN 0xFF 195 | // Below is general error code 196 | #define PS2_KEY_ERROR 0xFC 197 | 198 | /* Command parameters for functions */ 199 | /* LED codes OR together */ 200 | #define PS2_LOCK_SCROLL 0x01 201 | #define PS2_LOCK_NUM 0x02 202 | #define PS2_LOCK_CAPS 0x04 203 | /* Only useful for very few keyboards */ 204 | #define PS2_LOCK_EXTRA 0x08 205 | 206 | /* Returned keycode definitions */ 207 | /* Do NOT change these codings as you will break base 208 | functionality use PS2KeyMap for that and internationalisation */ 209 | #define PS2_KEY_NUM 0x01 210 | #define PS2_KEY_SCROLL 0x02 211 | #define PS2_KEY_CAPS 0x03 212 | #define PS2_KEY_PRTSCR 0x04 213 | #define PS2_KEY_PAUSE 0x05 214 | #define PS2_KEY_L_SHIFT 0x06 215 | #define PS2_KEY_R_SHIFT 0x07 216 | #define PS2_KEY_L_CTRL 0X08 217 | #define PS2_KEY_R_CTRL 0X09 218 | #define PS2_KEY_L_ALT 0x0A 219 | #define PS2_KEY_R_ALT 0x0B 220 | /* Sometimes called windows key */ 221 | #define PS2_KEY_L_GUI 0x0C 222 | #define PS2_KEY_R_GUI 0x0D 223 | #define PS2_KEY_MENU 0x0E 224 | /* Break is CTRL + PAUSE generated inside keyboard */ 225 | #define PS2_KEY_BREAK 0x0F 226 | /* Generated by some keyboards by ALT and PRTSCR */ 227 | #define PS2_KEY_SYSRQ 0x10 228 | #define PS2_KEY_HOME 0x11 229 | #define PS2_KEY_END 0x12 230 | #define PS2_KEY_PGUP 0x13 231 | #define PS2_KEY_PGDN 0x14 232 | #define PS2_KEY_L_ARROW 0x15 233 | #define PS2_KEY_R_ARROW 0x16 234 | #define PS2_KEY_UP_ARROW 0x17 235 | #define PS2_KEY_DN_ARROW 0x18 236 | #define PS2_KEY_INSERT 0x19 237 | #define PS2_KEY_DELETE 0x1A 238 | #define PS2_KEY_ESC 0x1B 239 | #define PS2_KEY_BS 0x1C 240 | #define PS2_KEY_TAB 0x1D 241 | #define PS2_KEY_ENTER 0x1E 242 | #define PS2_KEY_SPACE 0x1F 243 | #define PS2_KEY_KP0 0x20 244 | #define PS2_KEY_KP1 0x21 245 | #define PS2_KEY_KP2 0x22 246 | #define PS2_KEY_KP3 0x23 247 | #define PS2_KEY_KP4 0x24 248 | #define PS2_KEY_KP5 0x25 249 | #define PS2_KEY_KP6 0x26 250 | #define PS2_KEY_KP7 0x27 251 | #define PS2_KEY_KP8 0x28 252 | #define PS2_KEY_KP9 0x29 253 | #define PS2_KEY_KP_DOT 0x2A 254 | #define PS2_KEY_KP_ENTER 0x2B 255 | #define PS2_KEY_KP_PLUS 0x2C 256 | #define PS2_KEY_KP_MINUS 0x2D 257 | #define PS2_KEY_KP_TIMES 0x2E 258 | #define PS2_KEY_KP_DIV 0x2F 259 | #define PS2_KEY_0 0X30 260 | #define PS2_KEY_1 0X31 261 | #define PS2_KEY_2 0X32 262 | #define PS2_KEY_3 0X33 263 | #define PS2_KEY_4 0X34 264 | #define PS2_KEY_5 0X35 265 | #define PS2_KEY_6 0X36 266 | #define PS2_KEY_7 0X37 267 | #define PS2_KEY_8 0X38 268 | #define PS2_KEY_9 0X39 269 | #define PS2_KEY_APOS 0X3A 270 | #define PS2_KEY_COMMA 0X3B 271 | #define PS2_KEY_MINUS 0X3C 272 | #define PS2_KEY_DOT 0X3D 273 | #define PS2_KEY_DIV 0X3E 274 | /* Some Numeric keyboards have an '=' on right keypad */ 275 | #define PS2_KEY_KP_EQUAL 0x3F 276 | /* Single quote or back quote */ 277 | #define PS2_KEY_SINGLE 0X40 278 | #define PS2_KEY_A 0X41 279 | #define PS2_KEY_B 0X42 280 | #define PS2_KEY_C 0X43 281 | #define PS2_KEY_D 0X44 282 | #define PS2_KEY_E 0X45 283 | #define PS2_KEY_F 0X46 284 | #define PS2_KEY_G 0X47 285 | #define PS2_KEY_H 0X48 286 | #define PS2_KEY_I 0X49 287 | #define PS2_KEY_J 0X4A 288 | #define PS2_KEY_K 0X4B 289 | #define PS2_KEY_L 0X4C 290 | #define PS2_KEY_M 0X4D 291 | #define PS2_KEY_N 0X4E 292 | #define PS2_KEY_O 0X4F 293 | #define PS2_KEY_P 0X50 294 | #define PS2_KEY_Q 0X51 295 | #define PS2_KEY_R 0X52 296 | #define PS2_KEY_S 0X53 297 | #define PS2_KEY_T 0X54 298 | #define PS2_KEY_U 0X55 299 | #define PS2_KEY_V 0X56 300 | #define PS2_KEY_W 0X57 301 | #define PS2_KEY_X 0X58 302 | #define PS2_KEY_Y 0X59 303 | #define PS2_KEY_Z 0X5A 304 | #define PS2_KEY_SEMI 0X5B 305 | #define PS2_KEY_BACK 0X5C 306 | #define PS2_KEY_OPEN_SQ 0X5D 307 | #define PS2_KEY_CLOSE_SQ 0X5E 308 | #define PS2_KEY_EQUAL 0X5F 309 | /* Some Numeric keypads have a comma key */ 310 | #define PS2_KEY_KP_COMMA 0x60 311 | #define PS2_KEY_F1 0X61 312 | #define PS2_KEY_F2 0X62 313 | #define PS2_KEY_F3 0X63 314 | #define PS2_KEY_F4 0X64 315 | #define PS2_KEY_F5 0X65 316 | #define PS2_KEY_F6 0X66 317 | #define PS2_KEY_F7 0X67 318 | #define PS2_KEY_F8 0X68 319 | #define PS2_KEY_F9 0X69 320 | #define PS2_KEY_F10 0X6A 321 | #define PS2_KEY_F11 0X6B 322 | #define PS2_KEY_F12 0X6C 323 | #define PS2_KEY_F13 0X6D 324 | #define PS2_KEY_F14 0X6E 325 | #define PS2_KEY_F15 0X6F 326 | #define PS2_KEY_F16 0X70 327 | #define PS2_KEY_F17 0X71 328 | #define PS2_KEY_F18 0X72 329 | #define PS2_KEY_F19 0X73 330 | #define PS2_KEY_F20 0X74 331 | #define PS2_KEY_F21 0X75 332 | #define PS2_KEY_F22 0X76 333 | #define PS2_KEY_F23 0X77 334 | #define PS2_KEY_F24 0X78 335 | #define PS2_KEY_NEXT_TR 0X79 336 | #define PS2_KEY_PREV_TR 0X7A 337 | #define PS2_KEY_STOP 0X7B 338 | #define PS2_KEY_PLAY 0X7C 339 | #define PS2_KEY_MUTE 0X7D 340 | #define PS2_KEY_VOL_UP 0X7E 341 | #define PS2_KEY_VOL_DN 0X7F 342 | #define PS2_KEY_MEDIA 0X80 343 | #define PS2_KEY_EMAIL 0X81 344 | #define PS2_KEY_CALC 0X82 345 | #define PS2_KEY_COMPUTER 0X83 346 | #define PS2_KEY_WEB_SEARCH 0X84 347 | #define PS2_KEY_WEB_HOME 0X85 348 | #define PS2_KEY_WEB_BACK 0X86 349 | #define PS2_KEY_WEB_FORWARD 0X87 350 | #define PS2_KEY_WEB_STOP 0X88 351 | #define PS2_KEY_WEB_REFRESH 0X89 352 | #define PS2_KEY_WEB_FAVOR 0X8A 353 | #define PS2_KEY_EUROPE2 0X8B 354 | #define PS2_KEY_POWER 0X8C 355 | #define PS2_KEY_SLEEP 0X8D 356 | #define PS2_KEY_WAKE 0X90 357 | #define PS2_KEY_INTL1 0X91 358 | #define PS2_KEY_INTL2 0X92 359 | #define PS2_KEY_INTL3 0X93 360 | #define PS2_KEY_INTL4 0X94 361 | #define PS2_KEY_INTL5 0X95 362 | #define PS2_KEY_LANG1 0X96 363 | #define PS2_KEY_LANG2 0X97 364 | #define PS2_KEY_LANG3 0X98 365 | #define PS2_KEY_LANG4 0X99 366 | #define PS2_KEY_LANG5 0xA0 367 | 368 | /* 369 | Purpose: Provides advanced access to PS2 keyboards 370 | Public class definitions 371 | 372 | See standard error codes for error code returns 373 | */ 374 | class PS2KeyAdvanced { 375 | public: 376 | /* This constructor does basically nothing. Please call the begin(int,int) 377 | method before using any other method of this class. */ 378 | PS2KeyAdvanced( ); 379 | 380 | /* Starts the keyboard "service" by registering the external interrupt. 381 | setting the pin modes correctly and driving those needed to high. 382 | Sets default LOCK status (LEDs) to passed in value or default of all off 383 | The best place to call this method is in the setup routine. */ 384 | void begin( uint8_t, uint8_t ); 385 | 386 | /* Returns number of codes available or 0 for none */ 387 | uint8_t available( ); 388 | 389 | /* Returns the key last read from the keyboard. 390 | If there is no key available, 0 is returned. */ 391 | uint16_t read( ); 392 | 393 | /* Returns the current status of Locks 394 | Use Macro to mask out bits from 395 | PS2_LOCK_NUM PS2_LOCK_CAPS PS2_LOCK_SCROLL */ 396 | uint8_t getLock( ); 397 | 398 | /* Sets the current status of Locks and LEDs 399 | Use macro defines added together from 400 | PS2_LOCK_NUM PS2_LOCK_CAPS PS2_LOCK_SCROLL */ 401 | void setLock( byte ); 402 | 403 | /* Set library to not send break key codes 404 | 1 = no break codes 405 | 0 = send break codes */ 406 | void setNoBreak( uint8_t ); 407 | 408 | /* Set library to not repeat make codes for CTRL, ALT, GUI, SHIFT 409 | 1 = no repeat codes 410 | 0 = send repeat codes */ 411 | void setNoRepeat( uint8_t ); 412 | 413 | /* Resets keyboard when reset has completed 414 | keyboard sends AA - Pass or FC for fail 415 | Read from keyboard data buffer */ 416 | void resetKey( ); 417 | 418 | /* Get the current Scancode Set used in keyboard 419 | returned data in keyboard buffer read as keys */ 420 | void getScanCodeSet( void ); 421 | 422 | /* Get the current Scancode Set used in keyboard 423 | returned data in keyboard buffer read as keys */ 424 | void readID( void ); 425 | 426 | /* Send Echo command to keyboard 427 | returned data in keyboard buffer read as keys */ 428 | void echo( void ); 429 | 430 | /* Send Typematic rate/delay command to keyboard 431 | First Parameter rate is 0 - 0x1F (31) 432 | 0 = 30 CPS 433 | 0x1F = 2 CPS 434 | default in keyboard is 0xB (10.9 CPS) 435 | Second Parameter delay is 0 - 3 for 0.25s to 1s in 0.25 increments 436 | default in keyboard is 1 = 0.5 second delay 437 | Returned data in keyboard buffer read as keys */ 438 | int typematic( uint8_t , uint8_t ); 439 | }; 440 | #endif 441 | -------------------------------------------------------------------------------- /src/PS2KeyCode.h: -------------------------------------------------------------------------------- 1 | /* Version V1.0.8 2 | PS2KeyCode.h - PS2KeyAdvanced library Internal actual PS2 key code sequences 3 | Copyright (c) 2007 Free Software Foundation. All right reserved. 4 | Written by Paul Carpenter, PC Services 5 | Created September 2014 6 | Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management 7 | Updated December 2019 - Paul Carpenter - Fix typo in code for Multimedia STOP 8 | 9 | PRIVATE to library 10 | 11 | Test History 12 | September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 13 | January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board 14 | Manager V1.6.6 15 | 16 | This is for a LATIN style keyboard. Will support most keyboards even ones 17 | with multimedia keys or even 24 function keys. 18 | 19 | Definitions used for key codes from a PS2 keyboard, do not use in your 20 | code these are to be handled INTERNALLY by the library. 21 | (may disappear in updates do not rely on this file or definitions) 22 | 23 | See PS2KeyAdvanced.h for codes returned from library and flag settings 24 | 25 | Defines are in three groups 26 | 27 | Special codes definition of communications bytes 28 | 29 | Single Byte codes returned as key codes 30 | 31 | Two byte Codes preceded by E0 code returned as keycodes 32 | 33 | This library is free software; you can redistribute it and/or 34 | modify it under the terms of the GNU Lesser General Public 35 | License as published by the Free Software Foundation; either 36 | version 2.1 of the License, or (at your option) any later version. 37 | 38 | This library is distributed in the hope that it will be useful, 39 | but WITHOUT ANY WARRANTY; without even the implied warranty of 40 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 41 | Lesser General Public License for more details. 42 | 43 | You should have received a copy of the GNU Lesser General Public 44 | License along with this library; if not, write to the Free Software 45 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 46 | */ 47 | 48 | #ifndef PS2KeyCode_h 49 | #define PS2KeyCode_h 50 | 51 | /* Ignore code for key code translation */ 52 | #define PS2_KEY_IGNORE 0xBB 53 | 54 | // buffer sizes keyboard RX and TX, then key reading buffer 55 | // Minimum size 8 can be larger 56 | #define _RX_BUFFER_SIZE 8 57 | // Minimum size 6 can be larger 58 | #define _TX_BUFFER_SIZE 6 59 | // Output Buffer of unsigned int values. Minimum size 4 can be larger 60 | #define _KEY_BUFF_SIZE 4 61 | 62 | /* private defines for library files not global */ 63 | /* _ps2mode status flags */ 64 | #define _PS2_BUSY 0x80 65 | #define _TX_MODE 0x40 66 | #define _BREAK_KEY 0x20 67 | #define _WAIT_RESPONSE 0x10 68 | #define _E0_MODE 0x08 69 | #define _E1_MODE 0x04 70 | #define _LAST_VALID 0x02 71 | 72 | /* _tx_ready flags */ 73 | #define _HANDSHAKE 0x80 74 | #define _COMMAND 0x01 75 | 76 | /* Key Repeat defines */ 77 | #define _NO_BREAKS 0x08 78 | #define _NO_REPEATS 0x80 79 | 80 | /* PS2_keystatus byte masks (from 16 bit int masks) */ 81 | #define _BREAK ( PS2_BREAK >> 8 ) 82 | #define _SHIFT ( PS2_SHIFT >> 8 ) 83 | #define _CTRL ( PS2_CTRL >> 8 ) 84 | #define _CAPS ( PS2_CAPS >> 8 ) 85 | #define _ALT ( PS2_ALT >> 8 ) 86 | #define _ALT_GR ( PS2_ALT_GR >> 8 ) 87 | #define _GUI ( PS2_GUI >> 8 ) 88 | #define _FUNCTION ( PS2_FUNCTION >> 8 ) 89 | 90 | /* General defines of comms codes */ 91 | /* Command or response */ 92 | #define PS2_KC_RESEND 0xFE 93 | #define PS2_KC_ACK 0xFA 94 | #define PS2_KC_ECHO 0xEE 95 | /* Responses */ 96 | #define PS2_KC_BAT 0xAA 97 | // Actually buffer overrun 98 | #define PS2_KC_OVERRUN 0xFF 99 | // Below is general error code 100 | #define PS2_KC_ERROR 0xFC 101 | #define PS2_KC_KEYBREAK 0xF0 102 | #define PS2_KC_EXTEND1 0xE1 103 | #define PS2_KC_EXTEND 0xE0 104 | /* Commands */ 105 | #define PS2_KC_RESET 0xFF 106 | #define PS2_KC_DEFAULTS 0xF6 107 | #define PS2_KC_DISABLE 0xF5 108 | #define PS2_KC_ENABLE 0xF4 109 | #define PS2_KC_RATE 0xF3 110 | #define PS2_KC_READID 0xF2 111 | #define PS2_KC_SCANCODE 0xF0 112 | #define PS2_KC_LOCK 0xED 113 | 114 | /* Single Byte Key Codes */ 115 | #define PS2_KC_NUM 0x77 116 | #define PS2_KC_SCROLL 0x7E 117 | #define PS2_KC_CAPS 0x58 118 | #define PS2_KC_L_SHIFT 0x12 119 | #define PS2_KC_R_SHIFT 0x59 120 | /* This is Left CTRL and ALT but Right version is in E0 with same code */ 121 | #define PS2_KC_CTRL 0X14 122 | #define PS2_KC_ALT 0x11 123 | /* Generated by some keyboards by ALT and PRTSCR */ 124 | #define PS2_KC_SYSRQ 0x84 125 | #define PS2_KC_ESC 0x76 126 | #define PS2_KC_BS 0x66 127 | #define PS2_KC_TAB 0x0D 128 | #define PS2_KC_ENTER 0x5A 129 | #define PS2_KC_SPACE 0x29 130 | #define PS2_KC_KP0 0x70 131 | #define PS2_KC_KP1 0x69 132 | #define PS2_KC_KP2 0x72 133 | #define PS2_KC_KP3 0x7A 134 | #define PS2_KC_KP4 0x6B 135 | #define PS2_KC_KP5 0x73 136 | #define PS2_KC_KP6 0x74 137 | #define PS2_KC_KP7 0x6C 138 | #define PS2_KC_KP8 0x75 139 | #define PS2_KC_KP9 0x7D 140 | #define PS2_KC_KP_DOT 0x71 141 | #define PS2_KC_KP_PLUS 0x79 142 | #define PS2_KC_KP_MINUS 0x7B 143 | #define PS2_KC_KP_TIMES 0x7C 144 | /* Some keyboards have an '=' on right keypad */ 145 | #define PS2_KC_KP_EQUAL 0x0F 146 | #define PS2_KC_0 0X45 147 | #define PS2_KC_1 0X16 148 | #define PS2_KC_2 0X1E 149 | #define PS2_KC_3 0X26 150 | #define PS2_KC_4 0X25 151 | #define PS2_KC_5 0X2E 152 | #define PS2_KC_6 0X36 153 | #define PS2_KC_7 0X3D 154 | #define PS2_KC_8 0X3E 155 | #define PS2_KC_9 0X46 156 | #define PS2_KC_APOS 0X52 157 | #define PS2_KC_COMMA 0X41 158 | #define PS2_KC_MINUS 0X4E 159 | #define PS2_KC_DOT 0X49 160 | #define PS2_KC_DIV 0X4A 161 | /* Single quote or back apostrophe */ 162 | #define PS2_KC_SINGLE 0X0E 163 | #define PS2_KC_A 0X1C 164 | #define PS2_KC_B 0X32 165 | #define PS2_KC_C 0X21 166 | #define PS2_KC_D 0X23 167 | #define PS2_KC_E 0X24 168 | #define PS2_KC_F 0X2B 169 | #define PS2_KC_G 0X34 170 | #define PS2_KC_H 0X33 171 | #define PS2_KC_I 0X43 172 | #define PS2_KC_J 0X3B 173 | #define PS2_KC_K 0X42 174 | #define PS2_KC_L 0X4B 175 | #define PS2_KC_M 0X3A 176 | #define PS2_KC_N 0X31 177 | #define PS2_KC_O 0X44 178 | #define PS2_KC_P 0X4D 179 | #define PS2_KC_Q 0X15 180 | #define PS2_KC_R 0X2D 181 | #define PS2_KC_S 0X1B 182 | #define PS2_KC_T 0X2C 183 | #define PS2_KC_U 0X3C 184 | #define PS2_KC_V 0X2A 185 | #define PS2_KC_W 0X1D 186 | #define PS2_KC_X 0X22 187 | #define PS2_KC_Y 0X35 188 | #define PS2_KC_Z 0X1A 189 | #define PS2_KC_SEMI 0X4C 190 | #define PS2_KC_BACK 0X5D 191 | // Extra key left of Z on 102 keyboards 192 | #define PS2_KC_EUROPE2 0x61 193 | #define PS2_KC_OPEN_SQ 0X54 194 | #define PS2_KC_CLOSE_SQ 0X5B 195 | #define PS2_KC_EQUAL 0X55 196 | #define PS2_KC_F1 0X05 197 | #define PS2_KC_F2 0X06 198 | #define PS2_KC_F3 0X04 199 | #define PS2_KC_F4 0X0C 200 | #define PS2_KC_F5 0X03 201 | #define PS2_KC_F6 0X0B 202 | #define PS2_KC_F7 0X83 203 | #define PS2_KC_F8 0X0A 204 | #define PS2_KC_F9 0X01 205 | #define PS2_KC_F10 0X09 206 | #define PS2_KC_F11 0X78 207 | #define PS2_KC_F12 0X07 208 | #define PS2_KC_F13 0X08 209 | #define PS2_KC_F14 0X10 210 | #define PS2_KC_F15 0X18 211 | #define PS2_KC_F16 0X20 212 | #define PS2_KC_F17 0X28 213 | #define PS2_KC_F18 0X30 214 | #define PS2_KC_F19 0X38 215 | #define PS2_KC_F20 0X40 216 | #define PS2_KC_F21 0X48 217 | #define PS2_KC_F22 0X50 218 | #define PS2_KC_F23 0X57 219 | #define PS2_KC_F24 0X5F 220 | #define PS2_KC_KP_COMMA 0X6D 221 | #define PS2_KC_INTL1 0X51 222 | #define PS2_KC_INTL2 0X13 223 | #define PS2_KC_INTL3 0X6A 224 | #define PS2_KC_INTL4 0X64 225 | #define PS2_KC_INTL5 0X67 226 | #define PS2_KC_LANG1 0XF2 227 | #define PS2_KC_LANG2 0XF1 228 | #define PS2_KC_LANG3 0X63 229 | #define PS2_KC_LANG4 0X62 230 | #define PS2_KC_LANG5 0X5F 231 | 232 | /* Extended key codes E0 table for two byte codes */ 233 | /* PS2_CTRL and PS2_ALT Need using in any table for the right keys */ 234 | /* first is special case for PRTSCR not always used so ignored by decoding */ 235 | #define PS2_KC_IGNORE 0x12 236 | #define PS2_KC_PRTSCR 0x7C 237 | /* Sometimes called windows key */ 238 | #define PS2_KC_L_GUI 0x1F 239 | #define PS2_KC_R_GUI 0x27 240 | #define PS2_KC_MENU 0x2F 241 | /* Break is CTRL + PAUSE generated inside keyboard */ 242 | #define PS2_KC_BREAK 0x7E 243 | #define PS2_KC_HOME 0x6C 244 | #define PS2_KC_END 0x69 245 | #define PS2_KC_PGUP 0x7D 246 | #define PS2_KC_PGDN 0x7A 247 | #define PS2_KC_L_ARROW 0x6B 248 | #define PS2_KC_R_ARROW 0x74 249 | #define PS2_KC_UP_ARROW 0x75 250 | #define PS2_KC_DN_ARROW 0x72 251 | #define PS2_KC_INSERT 0x70 252 | #define PS2_KC_DELETE 0x71 253 | #define PS2_KC_KP_ENTER 0x5A 254 | #define PS2_KC_KP_DIV 0x4A 255 | #define PS2_KC_NEXT_TR 0X4D 256 | #define PS2_KC_PREV_TR 0X15 257 | #define PS2_KC_STOP 0X3B 258 | #define PS2_KC_PLAY 0X34 259 | #define PS2_KC_MUTE 0X23 260 | #define PS2_KC_VOL_UP 0X32 261 | #define PS2_KC_VOL_DN 0X21 262 | #define PS2_KC_MEDIA 0X50 263 | #define PS2_KC_EMAIL 0X48 264 | #define PS2_KC_CALC 0X2B 265 | #define PS2_KC_COMPUTER 0X40 266 | #define PS2_KC_WEB_SEARCH 0X10 267 | #define PS2_KC_WEB_HOME 0X3A 268 | #define PS2_KC_WEB_BACK 0X38 269 | #define PS2_KC_WEB_FORWARD 0X30 270 | #define PS2_KC_WEB_STOP 0X28 271 | #define PS2_KC_WEB_REFRESH 0X20 272 | #define PS2_KC_WEB_FAVOR 0X18 273 | #define PS2_KC_POWER 0X37 274 | #define PS2_KC_SLEEP 0X3F 275 | #define PS2_KC_WAKE 0X5E 276 | #endif 277 | -------------------------------------------------------------------------------- /src/PS2KeyTable.h: -------------------------------------------------------------------------------- 1 | /* Version V1.0.8 2 | PS2KeyTable.h - PS2KeyAdvanced library keycode values to return values 3 | Copyright (c) 2007 Free Software Foundation. All right reserved. 4 | Written by Paul Carpenter, PC Services 5 | Created September 2014 6 | V1.0.2 Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management 7 | 8 | PRIVATE to library 9 | 10 | Test History 11 | September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0 12 | January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board 13 | Manager V1.6.6 14 | 15 | Internal to library private tables 16 | (may disappear in updates do not rely on this file or definitions) 17 | 18 | This is for a LATIN style keyboard. Will support most keyboards even ones 19 | with multimedia keys or even 24 function keys. 20 | 21 | Definitions used for key codes from a PS2 keyboard, do not use in your 22 | code these are handled by the library. 23 | 24 | See PS2KeyAdvanced.h for codes returned from library and flag settings 25 | 26 | Two sets of tables 27 | 28 | Single Byte codes returned as key codes 29 | 30 | Two byte Codes preceded by E0 code returned as keycodes 31 | 32 | Same tables used for make and break decode 33 | 34 | Special cases are - 35 | 36 | PRTSCR that ignores one of the sequences (E0,12) as this is not always sent 37 | especially with modifier keys or some keyboards when typematic repeat comes on. 38 | 39 | PAUSE as this is an 8 byte sequence only one starting E1 so main code gets E1 40 | and waits for 7 more valid bytes to make the coding. 41 | 42 | This library is free software; you can redistribute it and/or 43 | modify it under the terms of the GNU Lesser General Public 44 | License as published by the Free Software Foundation; either 45 | version 2.1 of the License, or (at your option) any later version. 46 | 47 | This library is distributed in the hope that it will be useful, 48 | but WITHOUT ANY WARRANTY; without even the implied warranty of 49 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 50 | Lesser General Public License for more details. 51 | 52 | You should have received a copy of the GNU Lesser General Public 53 | License along with this library; if not, write to the Free Software 54 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 55 | */ 56 | #ifndef PS2KeyTable_h 57 | #define PS2KeyTable_h 58 | 59 | /* Table contents are pairs of numbers 60 | first code from keyboard 61 | second is either PS2_KEY_IGNOPRE code or key code to return 62 | 63 | Single byte Key table 64 | In codes can only be 1 - 0x9F, plus 0xF2 and 0xF1 65 | Out Codes in range 1 to 0x9F 66 | */ 67 | #if defined(PS2_REQUIRES_PROGMEM) 68 | const uint8_t PROGMEM single_key[][ 2 ] = { 69 | #else 70 | const uint8_t single_key[][ 2 ] = { 71 | #endif 72 | { PS2_KC_NUM, PS2_KEY_NUM }, 73 | { PS2_KC_SCROLL, PS2_KEY_SCROLL }, 74 | { PS2_KC_CAPS, PS2_KEY_CAPS }, 75 | { PS2_KC_L_SHIFT, PS2_KEY_L_SHIFT }, 76 | { PS2_KC_R_SHIFT, PS2_KEY_R_SHIFT }, 77 | { PS2_KC_CTRL, PS2_KEY_L_CTRL }, 78 | { PS2_KC_ALT, PS2_KEY_L_ALT }, 79 | { PS2_KC_SYSRQ, PS2_KEY_SYSRQ }, 80 | { PS2_KC_ESC, PS2_KEY_ESC }, 81 | { PS2_KC_BS, PS2_KEY_BS }, 82 | { PS2_KC_TAB, PS2_KEY_TAB }, 83 | { PS2_KC_ENTER, PS2_KEY_ENTER }, 84 | { PS2_KC_SPACE, PS2_KEY_SPACE }, 85 | { PS2_KC_KP0, PS2_KEY_KP0 }, 86 | { PS2_KC_KP1, PS2_KEY_KP1 }, 87 | { PS2_KC_KP2, PS2_KEY_KP2 }, 88 | { PS2_KC_KP3, PS2_KEY_KP3 }, 89 | { PS2_KC_KP4, PS2_KEY_KP4 }, 90 | { PS2_KC_KP5, PS2_KEY_KP5 }, 91 | { PS2_KC_KP6, PS2_KEY_KP6 }, 92 | { PS2_KC_KP7, PS2_KEY_KP7 }, 93 | { PS2_KC_KP8, PS2_KEY_KP8 }, 94 | { PS2_KC_KP9, PS2_KEY_KP9 }, 95 | { PS2_KC_KP_DOT, PS2_KEY_KP_DOT }, 96 | { PS2_KC_KP_PLUS, PS2_KEY_KP_PLUS }, 97 | { PS2_KC_KP_MINUS, PS2_KEY_KP_MINUS }, 98 | { PS2_KC_KP_TIMES, PS2_KEY_KP_TIMES }, 99 | { PS2_KC_KP_EQUAL, PS2_KEY_KP_EQUAL }, 100 | { PS2_KC_0, PS2_KEY_0 }, 101 | { PS2_KC_1, PS2_KEY_1 }, 102 | { PS2_KC_2, PS2_KEY_2 }, 103 | { PS2_KC_3, PS2_KEY_3 }, 104 | { PS2_KC_4, PS2_KEY_4 }, 105 | { PS2_KC_5, PS2_KEY_5 }, 106 | { PS2_KC_6, PS2_KEY_6 }, 107 | { PS2_KC_7, PS2_KEY_7 }, 108 | { PS2_KC_8, PS2_KEY_8 }, 109 | { PS2_KC_9, PS2_KEY_9 }, 110 | { PS2_KC_APOS, PS2_KEY_APOS }, 111 | { PS2_KC_COMMA, PS2_KEY_COMMA }, 112 | { PS2_KC_MINUS, PS2_KEY_MINUS }, 113 | { PS2_KC_DOT, PS2_KEY_DOT }, 114 | { PS2_KC_DIV, PS2_KEY_DIV }, 115 | { PS2_KC_SINGLE, PS2_KEY_SINGLE }, 116 | { PS2_KC_A, PS2_KEY_A }, 117 | { PS2_KC_B, PS2_KEY_B }, 118 | { PS2_KC_C, PS2_KEY_C }, 119 | { PS2_KC_D, PS2_KEY_D }, 120 | { PS2_KC_E, PS2_KEY_E }, 121 | { PS2_KC_F, PS2_KEY_F }, 122 | { PS2_KC_G, PS2_KEY_G }, 123 | { PS2_KC_H, PS2_KEY_H }, 124 | { PS2_KC_I, PS2_KEY_I }, 125 | { PS2_KC_J, PS2_KEY_J }, 126 | { PS2_KC_K, PS2_KEY_K }, 127 | { PS2_KC_L, PS2_KEY_L }, 128 | { PS2_KC_M, PS2_KEY_M }, 129 | { PS2_KC_N, PS2_KEY_N }, 130 | { PS2_KC_O, PS2_KEY_O }, 131 | { PS2_KC_P, PS2_KEY_P }, 132 | { PS2_KC_Q, PS2_KEY_Q }, 133 | { PS2_KC_R, PS2_KEY_R }, 134 | { PS2_KC_S, PS2_KEY_S }, 135 | { PS2_KC_T, PS2_KEY_T }, 136 | { PS2_KC_U, PS2_KEY_U }, 137 | { PS2_KC_V, PS2_KEY_V }, 138 | { PS2_KC_W, PS2_KEY_W }, 139 | { PS2_KC_X, PS2_KEY_X }, 140 | { PS2_KC_Y, PS2_KEY_Y }, 141 | { PS2_KC_Z, PS2_KEY_Z }, 142 | { PS2_KC_SEMI, PS2_KEY_SEMI }, 143 | { PS2_KC_BACK, PS2_KEY_BACK }, 144 | { PS2_KC_OPEN_SQ, PS2_KEY_OPEN_SQ }, 145 | { PS2_KC_CLOSE_SQ, PS2_KEY_CLOSE_SQ }, 146 | { PS2_KC_EQUAL, PS2_KEY_EQUAL }, 147 | { PS2_KC_EUROPE2, PS2_KEY_EUROPE2 }, 148 | { PS2_KC_F1, PS2_KEY_F1 }, 149 | { PS2_KC_F2, PS2_KEY_F2 }, 150 | { PS2_KC_F3, PS2_KEY_F3 }, 151 | { PS2_KC_F4, PS2_KEY_F4 }, 152 | { PS2_KC_F5, PS2_KEY_F5 }, 153 | { PS2_KC_F6, PS2_KEY_F6 }, 154 | { PS2_KC_F7, PS2_KEY_F7 }, 155 | { PS2_KC_F8, PS2_KEY_F8 }, 156 | { PS2_KC_F9, PS2_KEY_F9 }, 157 | { PS2_KC_F10, PS2_KEY_F10 }, 158 | { PS2_KC_F11, PS2_KEY_F11 }, 159 | { PS2_KC_F12, PS2_KEY_F12 }, 160 | { PS2_KC_F13, PS2_KEY_F13 }, 161 | { PS2_KC_F14, PS2_KEY_F14 }, 162 | { PS2_KC_F15, PS2_KEY_F15 }, 163 | { PS2_KC_F16, PS2_KEY_F16 }, 164 | { PS2_KC_F17, PS2_KEY_F17 }, 165 | { PS2_KC_F18, PS2_KEY_F18 }, 166 | { PS2_KC_F19, PS2_KEY_F19 }, 167 | { PS2_KC_F20, PS2_KEY_F20 }, 168 | { PS2_KC_F21, PS2_KEY_F21 }, 169 | { PS2_KC_F22, PS2_KEY_F22 }, 170 | { PS2_KC_F23, PS2_KEY_F23 }, 171 | { PS2_KC_F24, PS2_KEY_F24 }, 172 | { PS2_KC_KP_COMMA, PS2_KEY_KP_COMMA }, 173 | { PS2_KC_INTL1, PS2_KEY_INTL1 }, 174 | { PS2_KC_INTL2, PS2_KEY_INTL2 }, 175 | { PS2_KC_INTL3, PS2_KEY_INTL3 }, 176 | { PS2_KC_INTL4, PS2_KEY_INTL4 }, 177 | { PS2_KC_INTL5, PS2_KEY_INTL5 }, 178 | { PS2_KC_LANG1, PS2_KEY_LANG1 }, 179 | { PS2_KC_LANG2, PS2_KEY_LANG2 }, 180 | { PS2_KC_LANG3, PS2_KEY_LANG3 }, 181 | { PS2_KC_LANG4, PS2_KEY_LANG4 }, 182 | { PS2_KC_LANG5, PS2_KEY_LANG5 } 183 | }; 184 | 185 | /* Two byte Key table after an E0 byte received */ 186 | #if defined(PS2_REQUIRES_PROGMEM) 187 | const uint8_t PROGMEM extended_key[][ 2 ] = { 188 | #else 189 | const uint8_t extended_key[][ 2 ] = { 190 | #endif 191 | { PS2_KC_IGNORE, PS2_KEY_IGNORE }, 192 | { PS2_KC_PRTSCR, PS2_KEY_PRTSCR }, 193 | { PS2_KC_CTRL, PS2_KEY_R_CTRL }, 194 | { PS2_KC_ALT, PS2_KEY_R_ALT }, 195 | { PS2_KC_L_GUI, PS2_KEY_L_GUI }, 196 | { PS2_KC_R_GUI, PS2_KEY_R_GUI }, 197 | { PS2_KC_MENU, PS2_KEY_MENU }, 198 | { PS2_KC_BREAK, PS2_KEY_BREAK }, 199 | { PS2_KC_HOME, PS2_KEY_HOME }, 200 | { PS2_KC_END, PS2_KEY_END }, 201 | { PS2_KC_PGUP, PS2_KEY_PGUP }, 202 | { PS2_KC_PGDN, PS2_KEY_PGDN }, 203 | { PS2_KC_L_ARROW, PS2_KEY_L_ARROW }, 204 | { PS2_KC_R_ARROW, PS2_KEY_R_ARROW }, 205 | { PS2_KC_UP_ARROW, PS2_KEY_UP_ARROW }, 206 | { PS2_KC_DN_ARROW, PS2_KEY_DN_ARROW }, 207 | { PS2_KC_INSERT, PS2_KEY_INSERT }, 208 | { PS2_KC_DELETE, PS2_KEY_DELETE }, 209 | { PS2_KC_KP_ENTER, PS2_KEY_KP_ENTER }, 210 | { PS2_KC_KP_DIV, PS2_KEY_KP_DIV }, 211 | { PS2_KC_NEXT_TR, PS2_KEY_NEXT_TR }, 212 | { PS2_KC_PREV_TR, PS2_KEY_PREV_TR }, 213 | { PS2_KC_STOP, PS2_KEY_STOP }, 214 | { PS2_KC_PLAY, PS2_KEY_PLAY }, 215 | { PS2_KC_MUTE, PS2_KEY_MUTE }, 216 | { PS2_KC_VOL_UP, PS2_KEY_VOL_UP }, 217 | { PS2_KC_VOL_DN, PS2_KEY_VOL_DN }, 218 | { PS2_KC_MEDIA, PS2_KEY_MEDIA }, 219 | { PS2_KC_EMAIL, PS2_KEY_EMAIL }, 220 | { PS2_KC_CALC, PS2_KEY_CALC }, 221 | { PS2_KC_COMPUTER, PS2_KEY_COMPUTER }, 222 | { PS2_KC_WEB_SEARCH, PS2_KEY_WEB_SEARCH }, 223 | { PS2_KC_WEB_HOME, PS2_KEY_WEB_HOME }, 224 | { PS2_KC_WEB_BACK, PS2_KEY_WEB_BACK }, 225 | { PS2_KC_WEB_FORWARD, PS2_KEY_WEB_FORWARD }, 226 | { PS2_KC_WEB_STOP, PS2_KEY_WEB_STOP }, 227 | { PS2_KC_WEB_REFRESH, PS2_KEY_WEB_REFRESH }, 228 | { PS2_KC_WEB_FAVOR, PS2_KEY_WEB_FAVOR }, 229 | { PS2_KC_POWER, PS2_KEY_POWER }, 230 | { PS2_KC_SLEEP, PS2_KEY_SLEEP }, 231 | { PS2_KC_WAKE, PS2_KEY_WAKE } 232 | }; 233 | 234 | /* Scroll lock numeric keypad re-mappings for NOT NUMLOCK */ 235 | /* in translated code order order is important */ 236 | #if defined(PS2_REQUIRES_PROGMEM) 237 | const uint8_t PROGMEM scroll_remap[] = { 238 | #else 239 | const uint8_t scroll_remap[] = { 240 | #endif 241 | PS2_KEY_INSERT, // PS2_KEY_KP0 242 | PS2_KEY_END, // PS2_KEY_KP1 243 | PS2_KEY_DN_ARROW, // PS2_KEY_KP2 244 | PS2_KEY_PGDN, // PS2_KEY_KP3 245 | PS2_KEY_L_ARROW, // PS2_KEY_KP4 246 | PS2_KEY_IGNORE, // PS2_KEY_KP5 247 | PS2_KEY_R_ARROW, // PS2_KEY_KP6 248 | PS2_KEY_HOME, // PS2_KEY_KP7 249 | PS2_KEY_UP_ARROW, // PS2_KEY_KP8 250 | PS2_KEY_PGUP, // PS2_KEY_KP9 251 | PS2_KEY_DELETE // PS2_KEY_KP_DOT 252 | }; 253 | #endif 254 | --------------------------------------------------------------------------------