Quantcast eLuaPCKBD - eLua Wiki
Locked History Attachments

eLuaPCKBD

Information


Credits: Thiago Naves, Led Lab, PUC-Rio

Status: Stable

Runs on: All platforms

Description


This is a module to allow eLua programs to use a regular PC keyboard connected to any 4 GPIO pins of any eLua-capable platform.

Instructions


(coming soon ...)

Installing

Please refer to http://wiki.eluaproject.net/Tutorials/cmodules for installation instructions

Code


C module code

   1 /****************************************************************************/
   2 /*  pc_keyboard is a ps/2 keyboard driver for eLua ( www.eluaproject.net )  */
   3 /*                                                                          */
   4 /*         v0.2, June 2010, by Thiago Naves, LED Lab, PUC-Rio               */
   5 /*                                                                          */
   6 /****************************************************************************/
   7 
   8 /* Functions */
   9 
  10 /*
  11    - keyboard.init( Clock, Data, Clock PullDown, Data PullDown )
  12    - keyboard.setflags( Start, Stop, Parity )
  13    - keyboard.receive()
  14    - keyboard.send( Data )
  15    - keyboard.setleds( Num Lock, Caps Lock, Scroll Lock )
  16    - keyboard.disablekeyevents( Key code, Break, Typematic repeat )
  17    - keyboard.configkeys( Break, Typematic repeat )
  18    - keyboard.setrepeatrateanddelay( rate, delay )
  19    - keyboard.setscancodeset( Code set )
  20    - keyboard.enable()
  21    - keyboard.disable()
  22    - keyboard.reset()
  23    - keyboard.default()
  24    - keyboard.resend()
  25    - keyboard.echo()
  26 */
  27 
  28 #include "lua.h"
  29 #include "lualib.h"
  30 #include "lauxlib.h"
  31 #include "platform.h"
  32 #include "auxmods.h"
  33 #include "lrotable.h"
  34 #include "platform_conf.h"
  35 #include <string.h>
  36 
  37 #define MIN_OPT_LEVEL 2
  38 #include "lrodefs.h"
  39 
  40 #define DIR_OUT 0
  41 #define DIR_IN 1
  42 
  43 #define IGNORE 1
  44 #define USE 0
  45 
  46 #define ERROR 0
  47 
  48 #define ACK 0xFA
  49 #define SETLEDS 0xED
  50 #define ECHO 0xEE
  51 #define SET_TYPEMATIC_RD 0xF3
  52 #define SET_SCAN_CODE_SET 0xF0
  53 #define ENABLE 0xF4
  54 #define DISABLE 0xF5
  55 #define DEFAULT 0xF6
  56 #define RESET 0xFF
  57 #define RESEND 0xFE
  58 
  59 typedef struct sPin
  60 {
  61   pio_type pin, port;
  62 } tPin;
  63 
  64 /* Pin Configuration */
  65 tPin P_CLK, P_DATA, P_CLK_PD, P_DATA_PD;
  66 
  67 /* Start, Stop and Parity bits ignore configuration */
  68 char igStart = USE;
  69 char igStop = USE;
  70 char igParity = USE;
  71 
  72 /* Returns the absolut value of a number */
  73 static unsigned int abs( int i )
  74 {
  75   if ( i < 0 )
  76     return -i;
  77   else
  78     return i;
  79 }
  80 
  81 /* Converts a pin number got from the Lua stack to the tPin format */
  82 static tPin convertPin( int p )
  83 {
  84   tPin result;
  85   result.port = PLATFORM_IO_GET_PORT( p );
  86   result.pin = ( 1 << PLATFORM_IO_GET_PIN( p ) );
  87 
  88   return result;
  89 }
  90 
  91 /* Just to make the code easier to read
  92  * Sets a pin value ( 1 / 0 ) 
  93  */
  94 static void setPinVal( tPin p, char val )
  95 {
  96   if ( val )
  97     platform_pio_op( p.port, p.pin, PLATFORM_IO_PIN_SET );
  98   else
  99     platform_pio_op( p.port, p.pin, PLATFORM_IO_PIN_CLEAR );
 100 }
 101 
 102 /* Just to make the code easier to read
 103  * Sets a pin direction ( DIR_IN / DIR_OU )
 104  */
 105 static void setPinDir( tPin p, char dir )
 106 {
 107   if ( dir == DIR_IN )
 108     platform_pio_op( p.port, p.pin, PLATFORM_IO_PIN_DIR_INPUT );
 109   else
 110     platform_pio_op( p.port, p.pin, PLATFORM_IO_PIN_DIR_OUTPUT );
 111 }
 112 
 113 /* Just to make the code easier to read
 114  * Returns the current pin value 
 115  */
 116 static int getPinVal( tPin p )
 117 {
 118   return platform_pio_op( p.port, p.pin, PLATFORM_IO_PIN_GET );
 119 }
 120 
 121 /* Generates a Parity bit for a given char ( to send data ) */
 122 static char genCRC( unsigned char data )
 123 {
 124   int i, count;
 125 
 126   count = 0;
 127 
 128   /* Count the 1s */
 129   for ( i=0; i<8; i++ )
 130   {
 131     if ( ( data & 1 ) == 1 )
 132       count ++;
 133 
 134     data = data >> 1;
 135   }
 136 
 137   /* The parity bit is set if there is an even number of 1s  */
 138   return ( ( count & 1 ) != 1 );
 139 }
 140 
 141 /* Checks the Parity bit for a given package */
 142 static char checkCRC( unsigned int data )
 143 {
 144   /* Checks the parity bit ( odd parity ) */
 145   unsigned int tmp;
 146   int i, count;
 147 
 148   count = 0;
 149   tmp = data;
 150 
 151   /* Extract data bits */
 152   data = data >> 1;
 153   data = data & 255;
 154 
 155   /* Count the 1s */
 156   for ( i=0; i<8; i++ )
 157   {
 158     if ( ( data & 1 ) == 1 )
 159       count ++;
 160 
 161     data = data >> 1;
 162   }
 163 
 164   /* The parity bit is set if there is an even number of 1s  */
 165   return ( ( count & 1 ) != ( tmp & 512 ) );
 166 }
 167 
 168 /* Set IGNORE flags for Start, Stop and/or Parity bits
 169  * This is due to buggy keyboards
 170  * Lua: keyboard.setflags( Start, Stop, Parity )
 171  */
 172 static int keyboard_setflags( lua_State *L )
 173 { 
 174   /* Start, Stop, Parity */
 175   /* Set ignore bits flags */
 176   igStart = luaL_checkinteger( L, 1 );
 177   igStop = luaL_checkinteger( L, 2 );
 178   igParity = luaL_checkinteger( L, 3 );
 179 
 180   return 0;
 181 }
 182 
 183 /* Initializes pin directions and default values
 184  * Lua: keyboard.init( Clock, Data, Clock PullDown, Data PullDown ) 
 185  */
 186 static int keyboard_init( lua_State *L )
 187 {
 188   P_CLK = convertPin( luaL_checkinteger( L, 1 ) );
 189   P_DATA = convertPin( luaL_checkinteger( L, 2 ) );
 190   P_CLK_PD = convertPin( luaL_checkinteger( L, 3 ) );
 191   P_DATA_PD = convertPin( luaL_checkinteger( L, 4 ) );
 192 
 193   setPinDir( P_CLK_PD, DIR_OUT );
 194   setPinDir( P_DATA_PD, DIR_OUT );
 195   setPinDir( P_DATA, DIR_IN );
 196   setPinDir( P_CLK, DIR_IN );
 197 
 198   setPinVal( P_DATA_PD, 1 );
 199   setPinVal( P_CLK_PD, 1 );
 200 
 201   return 0;
 202 }
 203 
 204 /* Receives a char from the keyboard */
 205 static char keyboard_getchar( )
 206 {
 207   unsigned int data = 0;
 208 
 209   int i;
 210   for ( i=1; i<12; i++ )
 211   {
 212     while ( getPinVal( P_CLK ) != 1 ) /* Wait for next clock */
 213     {}
 214 
 215     if ( i < 11 )
 216       while ( getPinVal( P_CLK ) ) /* Wait for clock to go low */
 217       {}
 218 
 219     data = data >> 1;
 220 
 221     if ( getPinVal( P_DATA ) == 1 )
 222       data = data | ( 1 << 10 );
 223   }
 224 
 225   /* Check start bit */
 226   if ( ( ( data & 1 ) == 1 ) && ( igStart == USE ) )
 227     return ERROR;
 228 
 229   /* Check stop bit */
 230   if ( ( ( data & 1024 ) == 0 ) && ( igStop == USE ) )
 231     return ERROR;
 232 
 233   /* Check CRC bit */
 234   if ( ( checkCRC( data ) == 0 ) && ( igParity == USE ) )
 235     return ERROR;
 236 
 237   /* Remove Start, Stop and CRC bits */
 238   data = data >> 1;
 239   data = data & 255;
 240 
 241   return data;
 242 }
 243 
 244 /* Wrapper ( bind ) for keyboard_getchar function
 245  * Lua: keyboard.receive() 
 246  */
 247 static int keyboard_receive( lua_State *L )
 248 {
 249   lua_pushinteger( L, keyboard_getchar () );
 250   return 1;
 251 }
 252 
 253 /* Sends data to the keyboard */
 254 static void keyboard_write( char data )
 255 {
 256   char bit; /* Counter */
 257   char par = genCRC( data ); /* Parity Bit */
 258 
 259   
 260   /* Disable communication & Request Send */
 261   setPinVal( P_CLK_PD, 0 );
 262   platform_timer_delay( 1, 120 ); /* 120 microseconds */
 263   setPinVal( P_DATA_PD, 0 );
 264   setPinVal( P_CLK_PD, 1 );
 265 
 266   /* Wait for clock and send data */
 267   for ( bit=1; bit<= 11; bit++ )
 268   {
 269     while ( getPinVal( P_CLK ) == 1 )
 270     {}
 271 
 272     if ( bit == 9 ) /* Parity Bit */
 273       setPinVal( P_DATA_PD, par );
 274     else
 275       if ( bit == 10 ) /* Stop Bit */
 276         setPinVal( P_DATA_PD, 1 );
 277       else
 278         if ( bit != 11 ) /* Data Bit */
 279           setPinVal( P_DATA_PD, data & ( 1 << ( bit -1 ) ) );
 280 
 281     /* bit == 11 -> ACK bit, just ignore it */
 282 
 283     while ( getPinVal( P_CLK ) == 0 )
 284     {}
 285   }
 286 }
 287 
 288 /* Bind to keyboard_write function
 289  * Sends a byte to the Keyboard
 290  * Lua: keyboard.send( Data byte ) 
 291  */
 292 static int keyboard_send( lua_State *L )
 293 {
 294   int i;
 295   i = luaL_checkinteger( L, 1 );
 296   keyboard_write( i );
 297   return 0;
 298 }
 299 
 300 /* Sets the Num Lock, Caps Lock and Scroll Lock Leds state
 301  * Lua: keyboard.setleds( Num Lock, Caps Lock, Scroll Lock )
 302  */
 303 static int keyboard_setleds( lua_State *L )
 304 {
 305   int i = 0;
 306   i = i | ( luaL_checkinteger( L, 1 ) << 1 ); /* Num Lock */
 307   i = i | ( luaL_checkinteger( L, 2 ) << 2 ); /* Caps Lock */
 308   i = i | ( luaL_checkinteger( L, 3 ) ); /* Scroll Lock */
 309 
 310   keyboard_write( SETLEDS );
 311   keyboard_write( i );
 312 
 313   return 0;
 314 }
 315 
 316 /* Configure wich key events the keyboard will send for a given key
 317  * Params: Key code, Break, Typematic repeat
 318  * If param == USE then enable that message
 319  * If param == IGNORE then ignore that message
 320  * Lua: keyboard.disablekeyevents( Key, Break, Typematic )
 321  */
 322 static int keyboard_disablekeyevents( lua_State *L )
 323 {
 324   #define makeOnly 0xFD
 325   #define makeBreak 0xFC
 326   #define makeType 0xFB
 327   int bk, tp, i;
 328   char ret;
 329   const char * buf;
 330   size_t len;
 331 
 332   /* Get params */
 333   luaL_checktype( L, 1, LUA_TSTRING );
 334   buf = lua_tolstring( L, 1, &len );
 335   bk  = luaL_checkinteger( L, 2 );
 336   tp  = luaL_checkinteger( L, 3 );
 337 
 338   /* Send operation code */
 339   if ( ( bk == IGNORE ) && ( tp == IGNORE ) ) 
 340   {
 341     keyboard_write( makeOnly );
 342   }
 343 
 344   if ( ( bk == IGNORE ) && ( tp == USE ) )
 345   {
 346     keyboard_write( makeType );
 347   }
 348 
 349   if ( ( tp == IGNORE ) && ( bk == USE ) )
 350   {
 351     keyboard_write( makeBreak );
 352   }
 353 
 354   /* Wait for ACK */
 355   ret = keyboard_getchar();
 356 
 357   if ( ret != ACK )
 358   {
 359     printf( "Error: No ACK ! " );
 360     return 0;
 361   }
 362 
 363   /* send key ( make ) code */
 364   for ( i=0; i<len; i++ )
 365   {
 366     /* Send key code */
 367     keyboard_write( buf[i] );
 368 
 369     /* Wait for ACK */
 370     ret = keyboard_getchar();
 371 
 372     if ( ret != ACK )
 373     {
 374       printf( "Error: No ACK ! " );
 375       return 0;
 376     }
 377   }
 378 
 379   /* Send echo ( ends key list ) */
 380   keyboard_write( ECHO );
 381 
 382   return 0;
 383 }
 384 
 385 /* Configure wich key events the keyboard will send for all keys
 386  * If param == USE then enable that message
 387  * If param == IGNORE then ignore that message
 388  * Params: Break, Typematic repeat
 389  * Lua: keyboard.configkeys( Break, Typematic )
 390  */
 391 static int keyboard_configkeys( lua_State *L )
 392 {
 393   #define amakeOnly 0xF9
 394   #define amakeBreak 0xF8
 395   #define amakeType 0xF7
 396   #define amakeBreakType 0xFA
 397   int bk, tp;
 398   char ret;
 399 
 400   /* Get params */
 401   bk  = luaL_checkinteger( L, 1 );
 402   tp  = luaL_checkinteger( L, 2 );
 403 
 404   /* Enable all */
 405   keyboard_write( amakeBreakType );
 406 
 407   /* Wait for ACK */
 408   ret = keyboard_getchar();
 409 
 410   if ( ret != ACK )
 411   {
 412     printf( "Error: No ACK ! " );
 413     return 0;
 414   }
 415 
 416   /* Disable something ( or not ) */
 417 
 418   if ( ( bk == IGNORE ) && ( tp == IGNORE ) ) 
 419   {
 420     keyboard_write( amakeOnly );
 421   }
 422 
 423   if ( ( bk == IGNORE ) && ( tp == USE ) )
 424   {
 425     keyboard_write( amakeType );
 426   }
 427 
 428   if ( ( tp == IGNORE ) && ( bk == USE ) )
 429   {
 430     keyboard_write( amakeBreak );
 431   }
 432 
 433   /* Send echo ( ends key list ) */
 434   keyboard_write( ECHO );
 435 
 436   /* Wait for Echo reply */
 437   keyboard_getchar();
 438 
 439   return 0;
 440 }
 441 
 442 /* Defines the typematic delay and character repeat rate
 443  *
 444  * Typematic delay is the delay before repeating a character
 445  * when a key is hold down.
 446  * 
 447  * Repeat rate tells how many characters per second will be
 448  * sent after that delay 
 449  *
 450  * Lua: keyboard.setrepeatrateanddelay( rate, delay )
 451  */
 452 static int keyboard_setRepeatRateAndDelay( lua_State *L )
 453 {
 454   int rates[32] = { 300, 267, 240, 218, 207, 185, 171, 160, 150, 133, 120,
 455                     109, 100, 92, 86, 80, 75, 67, 60, 55, 50, 46, 43, 40, 
 456                     37, 33, 30, 27, 25, 23, 21, 20 };
 457 
 458   int delays[4] = { 250, 500, 750, 1000 };
 459 
 460   unsigned int rate, delay; /* Parameters sent by user */
 461   unsigned int i, rDiff, rateId; /* Used to find the rate closest to the param */
 462   unsigned int dDiff, delayId;   /* Used to find the delay closest to the param */
 463   unsigned int cmd; /* Control byte to send to the keyboard */
 464 
 465   rate = luaL_checkinteger( L, 1 );
 466   delay = luaL_checkinteger( L, 2 );
 467   
 468   /* Find the rate closest to the one passed */
 469   rDiff = abs( rate - rates[0] );
 470   dDiff = abs( delay - delays[0] );
 471   rateId = 0;
 472   delayId = 0;
 473 
 474   for ( i=1; i<32; i++ )
 475   {
 476     if ( abs( rate - rates[i] ) < rDiff )
 477     {
 478       rDiff = abs( rate - rates[i] );
 479       rateId = i;
 480     }
 481 
 482     if ( abs( rate - rates[i] ) > rDiff )
 483       break;
 484   }
 485 
 486   /* Find the delay closest to the one passed */ 
 487   for ( i=1; i<4; i++ )
 488   {
 489     if ( abs( delay - delays[i] ) < dDiff )
 490     {
 491       dDiff = abs( delay - delays[i] );
 492       delayId = i;
 493     }
 494 
 495     if ( abs( delay - delays[i] ) > dDiff )
 496       break;
 497   }
 498 
 499   cmd = rateId;
 500   cmd = cmd | delayId << 5; 
 501 
 502   keyboard_write( 0xF3 );
 503   keyboard_write( cmd );
 504 
 505   lua_pushinteger( L, rates[ rateId ] );
 506   lua_pushinteger( L, delays[ delayId ] );
 507 
 508   return 2;
 509 }
 510 
 511 /* Sets the used Key Scan Code Set ( 1, 2 or 3 )
 512  *
 513  * Lua: keyboard.setscancodeset( set )
 514  */
 515 static int keyboard_setScanCodeSet( lua_State *L )
 516 {
 517   int i = luaL_checkinteger( L, 1 );
 518 
 519   if ( ( i > 3 ) || ( i < 1 ) )
 520     return 0;
 521 
 522   /* Send Command Code */
 523   keyboard_write( SET_SCAN_CODE_SET );
 524 
 525   /* Wait for ACK */
 526   if ( keyboard_getchar() != ACK )
 527     return 0;
 528 
 529   /* Send Scan Set Code */
 530   keyboard_write( i );
 531 
 532   return 0;
 533 }
 534 
 535 /* Enables keyboard's key scanning after a disable command
 536  *
 537  * Lua: keyboard.enable()
 538  */
 539 static int keyboard_enable( lua_State *L )
 540 {
 541   keyboard_write( ENABLE );
 542   return 0;
 543 }
 544 
 545 /* Disable keyboard's key scanning ( keyboard stops looking for
 546  * pressed keys.
 547  *
 548  * Note: keyboard will return to the default configuration
 549  * ( see keyboard.default() command ).
 550  *
 551  * Lua: keyboard.disable()
 552  */
 553 static int keyboard_disable( lua_State *L )
 554 {
 555   keyboard_write( DISABLE );
 556   return 0;
 557 }
 558 
 559 /* Retuns keyboard to it's default state:
 560  * Typematic delay = 500ms
 561  * Typematic rate = 10.9 c.p.s
 562  * Keyboard sends key Make, Break and Typematic messages
 563  * Key Scan Code Set = 2
 564  *
 565  * Lua: keyboard.default()
 566  */
 567 static int keyboard_default( lua_State *L )
 568 {
 569   keyboard_write( DEFAULT );
 570   return 0;
 571 }
 572 
 573 /* Resets the keyboard
 574  *
 575  * Lua: keyboard.reset()
 576  */
 577 static int keyboard_reset( lua_State *L )
 578 {
 579   keyboard_write( RESET );
 580 
 581   /* Wait for ACK */
 582   keyboard_getchar();
 583 
 584   return 0;
 585 }
 586 
 587 /* Keyboards resends last byte, except if it was "resend".
 588  * In this case it sends the last non-resend byte.
 589  *
 590  * Lua: keyboard.resend()
 591  */
 592 static int keyboard_resend( lua_State *L )
 593 {
 594   /* Send command code */
 595   keyboard_write( RESEND );
 596 
 597   /* Returns the response */
 598   lua_pushinteger( L, keyboard_getchar() );
 599   return 1;
 600 }
 601 
 602 /* Keyboard responds with echo ( keyboard.ECHO - 0xEE )
 603  *
 604  * Lua: keyboard.echo()
 605  */
 606 static int keyboard_echo( lua_State *L )
 607 {
 608   /* Sends echo */
 609   keyboard_write( ECHO );
 610 
 611   /* Returns the response */
 612   lua_pushinteger( L, keyboard_getchar() );
 613 
 614   return 1;
 615 }
 616 
 617 const LUA_REG_TYPE keyboard_map[] = {
 618   { LSTRKEY( "init" ), LFUNCVAL( keyboard_init ) },
 619   { LSTRKEY( "receive" ), LFUNCVAL( keyboard_receive ) },
 620   { LSTRKEY( "setflags" ), LFUNCVAL( keyboard_setflags ) },
 621   { LSTRKEY( "send" ), LFUNCVAL( keyboard_send ) },
 622   { LSTRKEY( "setleds" ), LFUNCVAL( keyboard_setleds ) },
 623   { LSTRKEY( "configkeys" ), LFUNCVAL( keyboard_configkeys ) },
 624   { LSTRKEY( "disablekeyevents" ), LFUNCVAL( keyboard_disablekeyevents ) },
 625   { LSTRKEY( "setrepeatrateanddelay" ), LFUNCVAL( keyboard_setRepeatRateAndDelay) },
 626   { LSTRKEY( "setscancodeset" ), LFUNCVAL( keyboard_setScanCodeSet ) },
 627   { LSTRKEY( "reset" ), LFUNCVAL( keyboard_reset ) },
 628   { LSTRKEY( "enable" ), LFUNCVAL( keyboard_enable ) },
 629   { LSTRKEY( "disable" ), LFUNCVAL( keyboard_disable ) },
 630   { LSTRKEY( "default" ), LFUNCVAL( keyboard_default ) },
 631   { LSTRKEY( "resend" ), LFUNCVAL( keyboard_resend ) },
 632   { LSTRKEY( "echo" ), LFUNCVAL( keyboard_echo ) },
 633   { LSTRKEY( "ECHO" ), LNUMVAL( ECHO ) },
 634   { LSTRKEY( "IGNORE" ), LNUMVAL( IGNORE ) },
 635   { LSTRKEY( "USE" ), LNUMVAL( USE ) },
 636   { LSTRKEY( "ERROR" ), LNUMVAL( ERROR ) },
 637   { LSTRKEY( "ACK" ), LNUMVAL( ACK) },
 638   { LNILKEY, LNILVAL }
 639 };
 640 
 641 LUALIB_API int luaopen_keyboard ( lua_State *L )
 642 {
 643   LREGISTER( L, "keyboard", keyboard_map );
 644 };
 645 

Lua using example

   1 -----------------------------------------------------------------------------
   2 --    This file exemplifies the use of keyboard lib running on a MBED      --
   3 --    This example implements keyboard_read() function that prints         --
   4 --    received keys on screen.                                             --
   5 --    Note: Only letters a ~ z, space, shift and enter keys are            --
   6 --    implemented. Any other key will break the ( endless ) loop.          --
   7 
   8 local chars = {}
   9 
  10 chars[ 0x1C ] = "a"
  11 chars[ 0x32 ] = "b"
  12 chars[ 0x21 ] = "c"
  13 chars[ 0x23 ] = "d"
  14 chars[ 0x24 ] = "e"
  15 chars[ 0x2B ] = "f"
  16 chars[ 0x34 ] = "g"
  17 chars[ 0x33 ] = "h"
  18 chars[ 0x43 ] = "i"
  19 chars[ 0x3B ] = "j"
  20 chars[ 0x42 ] = "k"
  21 chars[ 0x4B ] = "l"
  22 chars[ 0x3A ] = "m"
  23 chars[ 0x31 ] = "n"
  24 chars[ 0x44 ] = "o"
  25 chars[ 0x4D ] = "p"
  26 chars[ 0x15 ] = "q"
  27 chars[ 0x2D ] = "r"
  28 chars[ 0x1B ] = "s"
  29 chars[ 0x2C ] = "t"
  30 chars[ 0x3C ] = "u"
  31 chars[ 0x2A ] = "v"
  32 chars[ 0x1D ] = "w"
  33 chars[ 0x22 ] = "x"
  34 chars[ 0x35 ] = "y"
  35 chars[ 0x1A ] = "z"
  36 chars[ 0x29 ] = " "
  37 -- chars[ 0x5A ] = "\n"
  38 
  39 function keyboard_read()
  40   local c
  41   local shift = false
  42 
  43   while true do
  44     c = keyboard.receive()
  45 
  46     -- check if it's the Shift key
  47     if ( c == 0x12 ) or ( c == 0x59 ) then -- Shift press
  48       shift = true
  49     else -- Shift release ( or other key press / release )
  50       if c == 0xF0 then
  51         c = keyboard.receive()
  52         if ( c == 0x12 ) or ( c == 0x59 ) then
  53           shift = false
  54         end
  55       else -- Other keys
  56         -- If it's a keyup message, ignore ( 2 bytes )
  57         if c == 0xF0 then
  58           keyboard.receive()
  59         else -- Else, print the Char
  60           if c == 0x5A then
  61             print( "" )
  62           else
  63             if chars[ c] == nil then
  64               print( "" )
  65               return
  66             else
  67               if shift then
  68                 term.print( string.upper( chars[ c ] ) )
  69               else
  70                 term.print( chars[ c ] )
  71               end;
  72             end
  73           end
  74         end
  75       end
  76     end
  77   end
  78 end
  79 
  80 -- Initialize the IOs
  81 keyboard.init( mbed.pio.P18, mbed.pio.P10, mbed.pio.P19, mbed.pio.P11 )
  82 
  83 -- Pins:
  84 -- Clock: Pin 18
  85 -- Data:  Pin 10
  86 -- Clock Pull Down: Pin 19
  87 -- Data Pull Down:  Pin 11
  88 
  89 -- Ignore stop bit ( buggy keyboard... )
  90 -- keyboard.setflags( 0, 1, 0 )
  91 keyboard.setflags( keyboard.USE, keyboard.IGNORE, keyboard.USE );
  92