A little technical blurb


The IR keyboard is part of a software chain, if you will. The lirc_serial daemon monitors the CD (Carrier Detect) input of the serial port. Attached to the CD input is the IR receiver diode (with some electronics to provide the diode with power and to drive the CD line). The lirc_serial kernel module is sampling that input every 1us, or so, looking for a transition. Once it sees the CD line toggling, it notes the transition interval timing and passes that information up the lircd daemon.

The lircd daemon has opened the /dev/lirc0 device and waits for the kernel driver to tell it that some activity is "heard". The transition timing data that lircd gets from lirc_serial is then "decoded". Our "codes" are in the /etc/lircd.conf file. Within that file is a complete description of how the pulse train is constructed along with a pattern matching table. When a series of pules are received, lircd looks up into the table to see which key it should say is being pressed.

From the output of the lircd daemon (/dev/lircd), the lirc_keybd daemon further processes the keystroke data and passes it into the system keyboard queue via the /dev/uinput (universal input device). From the uinput device, the key information is processed as if it had originated from a ps/2 keyboard! I thank Yann Vernier for his posting in the lirc mailing list for the idea on how to use the uinput device!

The neat thing about the lirc_keybd daemon is that you get to choose how to map the keys on the keyboard! The WebPal keyboard has a lot of interesting legends on the keys, like "Favs", "Mail", "Info"... And(!), irxevent can also be used to read the keys while lirc_keybd is also reading them. You can "unmap" a key from the table within lirc_keybd sources, recompile, then set an irxevent for that key. :) More on this later...

TopA look inside the keyboard.


8051 is large chip at left, 74HC393 is chip at right, Xmit IR diodes behind lens.

TopOkay, how does the keyboard work?

The keyboard contains an 8051 processor running at 3v and appears to be in a deep sleep mode of powerdown, until a key is pressed. The processor then appears to wakeup, scans to see which key it was, then sends two bytes out it's serial port, and goes back to sleep. There is a 74HC393 dual binary counter which divides the 4.9152MHz oscillator of the 8051 down to 38.4KHz. This 38.4KHz output of the counter chain drives the IR transmit diodes, this provides the carrier modulation for the Infra Red signal. The output of the 8051 UART drives the CLEAR (reset) line of the counters to turn the modulation on / off, depending on the state of the 8051 UART pin.

Some work with an oscilloscope and calculator suggests that 20bits are being sent, repeatedly, for each key. The bit duration is about 781.25us. This comes out to around 1280baud, this was verified through 8051 experience and a calculator. In the WebPal & Shannon, what they did to receive this data stream was to put another 8051 at the receiving side that also running at 4.9152MHz, and simply hooked the incoming demodulated bits to the UART RX pin. A pretty simple system really. Not very complicated at all, but effective.

The approach Yann Vernier took was to specify within his lircd.conf file that the transmission was an 8bit UART with odd parity. We then had to patch the lirc sources as there was nothing in the lirc source to handle an odd parity serial transmission. I did try this approach and I also seemed to be dropping charactors. I did see that he spec'ed the baudrate at 1250, instead of the 1280 I calculated / measured. When I set Yann's conf file to 1280 baud, nothing worked.

It was then that I realized there really wasn't much difference, or advantage, between telling lircd that it was to use either a serial data stream (UART) or to do pattern matching. Either way, lirc_serial driver would consume about the same amount of system time to decode either. The functions to pass a key input into the uinput device were kept, but everything else was discarded and new code was written.

TopHow it works

Okay, getting back to the lircd.conf file, I used irrecord to get a full set of transition timings (patterns), then I processed that file to make each transition time a multiple of 781 (781.25us for each data bit). When I did that, and tightened up the eps & aeps error tolerances, decoding became really reliable! Now all I had to do was to take the uinput primitives, build some code to read these decoded keys from /dev/lircd, process them, and pass them into the system keyboard buffer via /dev/uinput.

That is what lirc_keybd essentially does. The decoded IR stream is read from the lircd daemon (/dev/lircd), processed, and written into uninput (/dev/uinput). A normal key from the keyboard is strobed into uinput, as soon as the key is received, it is then toggled into the uinput device (keydown then keyup). The modifier keystrokes (shift, ctrl, alt, ...) keys are sensed, then kept track of their state so that CTRL-C, Alt-F1, etc. sequences can be done. These modifier keys are not strobed in as the other keys, but are sent as discrete KEYDOWN or KEYUP inputs as the real state of those key changes. Interestingly, there are codes sent for each KEYDOWN as well as KEYUP, and finally there is even a ALL_KEYS_UP type of code to tell you that nothing is now pressed! Nice job Sejin!

What is important is that the lirc_keybd daemon looks at the name of the remote control and will only process the information from lircd if it is the name of the remote compiled into lirc_keybd. You will also find that there is a "#define SHANNON" at the top of the lirc_keybd.c source file, set this to non-zero if you are going to use a TuxScreen (Shannon) keyboard instead of that of the WebPal (WebPals are cheaper!).

TopTo make this all work for a WebPal keyboard.

You need:
  • build an lirc_serial kernel module that matches your hardware (ttySx).
  • make sure NO OTHER lirc stuff is loaded, this includes lirc_i2c (ivtv)
  • modprobe lirc_serial into the modules stack
  • note which /dev/lircX was instantiated (usually /dev/lirc0)
  • copy lircd-webpal.conf to /etc/lircd.conf
  • start lircd with "lircd -d /dev/lirc0"
  • build lirc_keybd sources
  • install the lirc_keybd daemon with "./lirc_kdb"