IgorplugUDP.py - a Python Transcoder to Connect the Igorplug-UDP Device to the Common Linux Infrared Daemon LIRC/ Hardware for LIRC
Author: Dr. Frank Borkenhagen
25 February 2007
Background for this project:
Igor Cesko has created a great and cheap solution for recording infrared code from common remotes which broadcasts the recorded IR code to the network.
It was not possible to connect the device to the common Linux LIRC daemon. IgorplugUDP.py is a Python script which is designed to close this gap. IgorplugUDP.py receives data from the device, and after transcoding, the IR signal will be forwarded to any LIRC daemon via UDP.
Igor Cesko's device is a solid and very cheap device. The price for one device is approx. 15EUR plus the costs for one Atmel programmer (e.g AVR ISP mkII, 39EUR, www.segor.de ) plus the costs for one device case (price is up the user) plus price for a power supply (approx. 10EUR). I have tested the device with four different RC5 remotes (3x Hauppauge, 1x Naim) and with one non RC5 remote (Panasonic UR57EC679-1). From my current point of view all IR remotes, supported by LIRC, can be used. The connection via LIRC to the VDR works perfect.
Some pictures of my prototype can be found here.
Principle of work for the Python script IgorplugUDP.py:
The script receives UDP packages from Igor Cesko's device. This packages will be transcoded into lircd-UDP-packages and will be sent to any lircd daemon, connected to the network.
IgorplugUDP.py can be found here:.
Installation - Network:
Ensure that your PC/server (“machine”) has access to the used real/ logical network described as follows. In Igor's firmware the IP address of the device is set to 192.168.1.7, netmask is 255.255.255.0. The device sends to UDP port 6669. If there is no physical network for this address you should add a corresponding IP alias to one of your network devices. Adding an alias can be performed e.g. as follows: "ifconfig ethX:0 192.168.1.4 netmask 255.255.255.0" If X is 0 the first network device is meant. Now it is possible to get Igor's packages through the just created logical network. Routing to the device is not required because it is not able to get any network packages - it can only send packages. So it is possible to put some IgorplugUDP devices with the same MAC address into the same network. From the machine's point of view there is only one device in the network. There is no device setting which can be changed via any network operations.
Make sure that IgorplugUDP.py is copied into a directory which is covered by the root's PATH variable.
Start the script as root by executing "IgorplugUDP.py". The script will not fork in the background. For running the script in the background execute "IgorplugUDP.py &". It is not possible to start more than one instance because the port 6668 will be blocked by the first IgorplugUDP.py instance.
Lirc needs to be started with its own UDP driver enabled. If lirc was configured for the UDP driver only, just start lircd, if not start lircd with "lircd --driver=udp". It is possible to connect as much machines as you want to the device because Igorplug-UDP broadcasts to the whole network 192.168.1.255.
The hardware is described in Igor's homepage.
Power supply. The circuit needs a +5V power supply, +5V can be provided e.g. by a L4940V5 IC.
Programming the firmware into the ATMEGA48:
Igor provides the firmware via his homepage (udpmega48.hex). This file is included in IgorPlug-UDPSources.zip – see Igor's homepage. AVR studio provided by Atmel is required. Programming will be performed using any Atmel programmer which can be ordered from www.Segor.de (approx 39 EUR)
It is a must to set some Clock settings. Please find this settings in the following screenshots:
Possible changes for network settings:
Igor provides also the source code via his homepage. All settings has to be changed in Igor's assembler code. After saving the changes and compiling the firmware, the firmware can be programmed into the FLASH memory of the device. This can be done by using the software "AVR studio", provided by Atmel.
How it works:
ATMEGA48 vs. Igor's Firmware:
The Igorplug-UDP device is driven by a 20.000 MHz quartz, and the ATMEGA48 is set to use 20.000 MHz/ 1024 = 19531.25 Hz as the time base for time measurements. The shortest time for time measurements is 1/19531.25 Hz = 0,0000512 s = 0,0512 ms = 51,2 us. If a IR signal (space or pulse) would only be 0,0512 ms long, the device would record "10000000" (this is a 8 bit high endian integer) . If the space/ pulse length would be 2x0,0512 ms, "01000000" (this is a 8 bit high endian integer) would be recorded etc. Defined in the firmware, the maximal pulse/ space lengths is 12.8ms. A such space/ pulse would be recorded as "01011111", calculated by (250*0,0512 ms). Each space/ pulse stands for one bit in the IR code. Each bit in the IR code will be coded into one 8 bit high endian integer. The device queues this integers in the RAM until it was not able to measure any signal change within 12.8 ms. If there is no signal change, receiving of the IR code is completed and the device will send the queued signals packaged and coded via UDP to the network (UDP port 6668).
Coding of UDP packages:
On UDP package contains 44 data bytes. Each package starts with four CRC correction bytes, which can be used e.g. for validation purposes. The other 40 bytes has to be classifies as eight sets of five bytes. Each set of 5 bytes stands for one bit in the IR bit measurement (a 8 bit high endian integer). The first set (after the CRC correction bytes) describes the first bit. If the bit is high, the set is "0x80, 0x20, 0x83, 0xB8, 0xED" whereas "0x00, 0x00, 0x00, 0x00, 0x00" is the set in case of a low bit. 44bytes=4bytes + (8 * 5bytes)
Sending of IR code from the Igorplug-UDP device to the network:
For one IR code one set of UDP packages will be sent. One RC5 example can be found here. Depends from the received code one set contains 3+14+1=18 to approx 3+50+1=54 UDP packages. Each set of UDP packages starts with three header packages and ends with exactly one termination package. If the received IR code has n bits (spaces+pulses) the device will send 3+n+1 packages.
Decoding of Igor's UDP packages:
The first and second header package in one set of UDP packages can be ignored, respectively. The third package contains the 4 CRC correction bytes and 40x0x00 which is the start signal and stands for a very long space(>= 13,056 ms). Next all coded data packages will be sent, and last but not least a termination package will be sent (4 byte signature and 40x0xFF) - this is the stop signal and stands also for a very long space (>= 13,056 ms).
If the device would be able to measure times longer than 12.8 ms, the measurement for an 13,056 ms space/ pulse would be "11111111". Time measurements longer than this would not fit into 8 bit integers and can not be measured. The mayor information here is that "11111111" (0xFF) stands for 13,056 ms =(255*0,0512 ms). On the one hand, the time base for time measurements in the Iglorplug-UDP device is 19531.25 Hz . On the other hand, for the lircd daemon, the time base for time measurements is 16384 Hz. This difference must be use to adjust the timing during transcoding of signals. So each time measurements, performed by Igor's device must be divided by 1.1921 (19531.25 Hz/16384 Hz). Depends from the vendor's tolerance of used remote control it can be necessary to change this value within a small range e.g. 1.13).
Encoding of data into lircd UDP packages:
For one IR code the lircd-UDP interface (UDP port 8765) requires some 16 bit integers (little endian). Each 16 bit integer stands for one bit in the IR code. If the highest bit is high, a pulse is transferred, if this bit is low, a space is transferred. For one IR code a set of some 16 bit Integers will be send via UDP to the lircd daemon. The amount of 16 bit integers equals to the amount of IR code bits. The UDP package contains all of this 16 bit integers plus one start- 8- bit integer (0xFF) plus one stop- 8- bit integer (0xFF).
Lirc needs to be compiled with its own UDP driver enabled, and sometimes it is helpful to get debugging information from lirc. So the configure step should look like "./configure --with-driver=udp --enable-debug".