IRMP - english

Wechseln zu: Navigation, Suche

By Frank M. (ukw)

This is the English translation of the german IRMP documentation.

Scan eines NEC-kompatiblen Fernbedienungssignals

Project Intention:

Because RC5 isn't only outdated, today its already obsolete and because more and more electronic devices in consumer electronics around us are used, it is time to develop an IR-decoder that can 'understand' about 90 % of IR-remotes that are used in our daily life.

This article indroduces 'IRMP' as "Infrared-Multiprotocol-Decoder" in all details. The counterpart, IRSND as IR-Encoder can be found in this document.

Inhaltsverzeichnis

IRMP - Infrared Multiprotocol Decoder

Connection of a IR receiver module to MCU

Supported MCUs

IRMP has been implemented on several MCU families:

AVR

  • ATtiny87, ATtiny167
  • ATtiny45, ATtiny85
  • ATtiny44, ATtiny84
  • ATmega8, ATmega16, ATmega32
  • ATmega162
  • ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284
  • ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P

XMega

  • ATXmega128

PIC (CCS- and XC8/C18 compiler)

  • PIC12F1840
  • PIC18F4520

STM32

  • STM32F4xx (tested on STM32F401RE/F411RE Nucleo, STM32F4 Discovery)
  • STM32F10x (tested on STM32F103C8T6 Mini Development Board)

STM8 (NEW!)

  • STM8S103F3

TI Stellaris

  • LM4F120 Launchpad (ARM Cortex M4)

ESP8266 (NEW!)

  • ESP8266-EVB

TEENSY 3.0 (NEW!)

  • MK20DX256VLH7 (ARM Cortex-M4 72MHz)

MBED (NEW!)

  • LPC1347 Cortex-M3 72 MHz
  • LPC4088 (Embedded Artists)

Supported IR Protocols

IRMP - the infrared remote decoder, which can decode several protocols at once, is capable of decoding the following protocols (in alphabetic order):

supported protocols
Protocol Vendor
A1TVBOX ADB (Advanced Digital Broadcast), z.B. A1 TV Box
APPLE Apple
ACP24 Stiebel Eltron
B&O Bang & Olufsen
BOSE Bose
DENON Denon, Sharp
FAN FAN, remote for fans
FDC FDC Keyboard
GRUNDIG Grundig
NOKIA Nokia, e.g. D-Box
IR60 (SDA2008) various european vendors
JVC JVC
KASEIKYO Panasonic, Technics, Denon and other japanese vendors which are members of the "Japan's Association for Electric Home Application".
KATHREIN KATHREIN
LEGO Lego
LGAIR LG Air Conditioner
MATSUSHITA Matsushita
MITSU_HEAVY Mitsubishi Air Conditioner (NEW!)
NEC16 JVC, Daewoo
NEC42 JVC
MERLIN MERLIN remote (Pollin article number: 620 185)
NEC NEC, Yamaha, Canon, Tevion, Harman/Kardon, Hitachi, JVC, Pioneer, Toshiba, Xoro, Orion, NoName and many more asian vendors.
NETBOX Netbox
NIKON NIKON
NUBERT Nubert, e.g. Subwoofer Systems
ORTEK Ortek, Hama
PANASONIC PANASONIC Beamer (NEU!)
PENTAX PENTAX (NEU!)
RC5 Philips and other european vendors
RC6A Philips, Kathrein and others, e.g. XBOX
RC6 Philips and other european vendors
RCCAR RC Car: IR remote for RC toys
RECS80 Philips, Nokia, Thomson, Nordmende, Telefunken, Saba
RECS80EXT Philips, Technisat, Thomson, Nordmende, Telefunken, Saba
RCMM Fujitsu-Siemens e.g. Activy keyboard
ROOMBA iRobot Roomba vacuum cleaner
S100 similar to RC5, but 14 instead of 13 Bits and 56kHz modulation. vendor unknown.
SAMSUNG32 Samsung
SAMSUNG48 various air conditions
SAMSUNG Samsung
RUWIDO RUWIDO (e.g. T-Home-Mediareceiver, MERLIN-keyboard(Pollin))
SIEMENS Siemens, z.B. Gigaset M740AV
SIRCS Sony
SPEAKER Speaker Systems like X-Tensions
TECHNICS Technics
TELEFUNKEN Telefunken
THOMSON Thomson
VINCENT Vincent

Each of these protocols can be activated separately. If you want, you can activate all protocols. If you need only one protocol, you can disable all others. It will only be compiled the code that has been selected by the user.

History

The IRMP source for the AVR and PIC MCUs has been created as part of the Word Clock project.

Thread in Forum

Intention for an own IRMP article is the following thread in Projects&Code IRMP - Infrared Multi Protocol Decoder (in german language).

IR Protocols

NEC protocol, RGB remote control, T->A: 9,14ms, A->B: 4,42ms, B->C: 660us

Some vendors use their own proprietary protocol, such as Sony, Samsung and Matsuhita. Philips has developed RC5 and of course used for own purposes. RC5 was seen in Europe as that standard IR-protocol which was adopted by many european vendors. Nowadays is RC5 nearly nowhere used - it can be ticked as "dead". Although the successor RC6 is used in actual european hardware, it is also used rarely.

Also japanese vendors tried to establish an own standard, the so called Kaseikyo- (or also "Japan-") protocol. This is with a bitlength of 48 bits more versatile. But it has no general acceptance until today - even if you find it in some appliances.

Nowadays the NEC protocol is used (also mainly in japanese devices) - indeed in various premium and NoName products. I estimate the market share to 80 % for the NEC-protocol. Nearly all remotes in my daily use utilize the NEC-IR-Code. This starts at the TV-set, goes over the DVD-player to the Notebook remote and reaches up to NoName-Multimedaia-Harddrive, just to mention a few samples.

Codings

IRMP supports the following IR-Codings:

The pulses are modulated - usually with 36 kHz or 38 kHz - to reduce environment influences such as Indoorlightning or sunlight.

Pulse Distance

Pulse Distance Coding

A Pulse Distance Coding can be discovered by the following rule:

  • there is only one pulse length and there are two different pause lengths

Pulse Width

Pulse Width Coding

A Pulse Width Coding can be discovered by the following rule:

  • there are two different pulse lengths and only one pause length

Pulse Distance Width

Pulse Distance Width Coding

This is a mix from Pulse Distance and Pulse Width Coding, so:

  • there are two different pulse lengths and two different pause lengths.

Biphase

Biphase Coding

In Biphase Coding the order of pulse and pause gives the bit value. Therefore a Biphase-Coding can be discovered by this criteria:

  • there is exactly one pause- and one pulse length, as well as the double pulse/pause length

Usually the length for the pulse and pause are equal, that means the signal shape is symmetric. But IRMP knows also protocols which use different puls/pause lengths. This case is for example the A1TVBOX-protocol.

Pulse Position

Pulse Position Coding

The pulse position coding is known from usual UART's. Every bit has a fixed length here. Depending on the value (0 or 1), it is a pulse or a pause.

Typical criteria for a pulse position protocol is:

  • there are multiples of a basic pulse/pause length

A tabular listing of different IR-protocols can be found here: IR Protocols in Detail. The specified timings are typical values. In some remotes they differ up to 40 % in real life. Therefore IRMP uses minimum/maximum limits to be tolerant with the timing.

Protocol Detection

The most of the IRMP decoded protocols have something in common: they show a start bit which is unique for their timing.

According to this start bit timing the most protocols are discriminated. IRMP measures the timing of the start bit and reorders its timing tables "on-the-fly" for the discovered protocol. So the following bits can be read sequential without the need of storing a complete frame. IRMP does not wait for reading a complete frame to analyze, it starts decoding after the first pulse detection.

If the first read start bit is not unique, IRMP follows multiple possible protocols. If for plausible reasons one protocol is no more possible this track will be dropped.

The detection is implemented as a state machine, which is called interrupt driven with an frequency of typically 15.000 per second. the state machine knows the following states:

  • detect the first pulse length of the start bit
  • detect the pause length of the start bit
  • detect the pulse length of the first data bit

After that, the pulse/pause length of the start bit are known. Now all enabled protocols are searched for this length. If a protocol matches, the timing table for this protocol is loaded and the following bits are checked if the pulse/pause timing still fit to the limis.

So the state machine continues with the following states:

  • detect the pauses of the data bits
  • detect the pulse length of the data bits
  • check timing. If different, switch back to another valid IR protocol, otherwise return
  • detect the sop bit if present in the protocol
  • check data for plausibility, like CRC or other redundant data bits
  • convert data to device address and command
  • detect code repetition by long key press, set according flag

Indeed the state machine is even more complex because some protocols have no start bit (e.g. Denon) or have multiple start bits (4 in B&O) or have within the frame another sync bit (z.B. Samsung). These extra conditions are caught in the code by protocol specific "special cases".

Switching to an other protocol can happen multiple times during receiving of a frame, f.e. from NEC42 (42 Bit) to NEC16 (8 Bit + Sync-Bit + 8 Bit), when a premature sync bit was detected. Or from NEC/NEC42 (32/42 Bit) to JVC (16 Bit) when the stop bit premature occured. It is getting difficult when two possible protocols after the detection of the start bit use different codings, e.g. when the one protocol uses a Pulse Distance Coding and the other uses a Biphase Coding (Manchester). In this case IRMP stores the necessary bits for both codings and releases later the one or the other.

Furthermore some remotes are transmitting in particular protocols for redundance reasons (error detection) or for long key presses repetition frames. These will be discriminated by IRMP: the necessary frames for error detection are checked by IRMP, but not passed to the application. The other will be detected as long key press and flagged by IRMP.

Download

Version 3.0.8, Date: 2017-08-25

Download of stable version: Irmp.zip

IRMP & IRSND is also available by SVN: IRMP in SVN, Download Tarball, Git: IRMP on GitHub

Warning:

The version in the SVN can be a newer version than the stable version stored in Irmp.zip. In doubt, use the download link of Irmp.zip.

You can see the history of the software changes here: Software History

Source Code

The source code can be easily compiled for AVR MCUs by loading the project file irmp.aps in AVR Studio 4.

For other development environments it is simple to create a project or makefile. The source includes:

Sample applications (main functions and timer configurations):

Important
include only irmp.h to your application:
#include "irmp.h"

All other include files are included within irmp.h. See also the sample application irmp-main-avr.c.

Furthermore, the preprocessor constant F_CPU in project or makefile must be defined. This should have at least the value of 8000000UL, processor speed should be at least 8 MHz. This applies to AVR targets and not for MCUs with PLL.

IRMP is also running on PIC processors. For the PIC-CCS compiler are already the necessary preprocessor defines set, so that irmp.c can be directly used in the CCS environment. Only a short interrupt service routine like

void  TIMER2_isr(void) 
{
 irmp_ISR ();
}

must be added. The Interrupt period time must be set to 66 µs (15 kHz).

For AVR processors you will find an example for the usage of IRMP in irmp-main-avr.c. The main things are the Timer initializing of the timer and the processing of received IR commands. The received protocoll, the device address and the command will be output on the HW-UART.

For the Stellaris LM4F120 Launchpad from TI (ARM Cortex M4) is a propriate timer init function already integrated in irmp-main-avr.c.

IRMP can be used also with STM32 microcontrollers.

Another new implementation is available on the mbed platform.

avr-gcc Optimizations

From version avr-gcc 4.7.x the option LTO-Option can be used to make the call of the external function irmp_ISR() from the main ISR more efficent. This improves the performance of the ISR a little.

Add the following compiler- and linker options:

  • additional compiler option: -flto
  • additional linker options: -flto -Os

If you forget the additional linker option -Os, the binary will be significant larger as it will no be optimized further. Also the option -flto must be passed to the linker, otherwise the link time optimization will not work.

Configuration

The configuration of IRMP is done by settings in irmpconfig.h :

Adjustments in irmpconfig.h

IRMP will decode all protocols listed above in one ISR. For this, there are some settings necessary. These are set in irmpconfig.h.

F_INTERRUPTS

Number of interrupts per second. Should be set to a value from 10000 to 20000. The higher the value, the better the resolution and therefore the quality of detection. But a higher interrupt rate means also higher CPU load. The value of 15000 is in most cases a good compromise.

Standardvalues:

#define F_INTERRUPTS                            15000      // interrupts per second

On AVR controllers is a timer1 with 16 bit resolution used in the example irmp-main-avr.c. If for any reasons timer1 is not available, you can also use timer2 with 8 bit resolution.

In this case timer2 will be configured as:

OCR2   =  (uint8_t) ((F_CPU / F_INTERRUPTS) / 8) - 1 + 0.5);   // Compare Register OCR2
TCCR2  = (1 << WGM21) | (1 << CS21);                           // CTC Mode, prescaler = 8
TIMSK  = 1 << OCIE2;                                           // enable timer2 interrupt

The above example is valid for ATmega88/ATmega168/ATmega328. For other AVR MCUs check the datasheet.

You must not forget to adjust the ISR for timer2 as well:

ISR(TIMER2_COMP_vect)
{
  (void) irmp_ISR(); 
}

IRMP_SUPPORT_xxx_PROTOCOL

Here you can select which protocols should be supported by IRMP. Standardprotocols are activated by default.

Would you like to turn on more protocols or turn off some other for memory saving reasons, then the corresponding values in irmpconfig.h must be set.

// typical protocols, disable here!             Enable  Remarks                 F_INTERRUPTS            Program Space
#define IRMP_SUPPORT_SIRCS_PROTOCOL             1       // Sony SIRCS           >= 10000                 ~150 bytes
#define IRMP_SUPPORT_NEC_PROTOCOL               1       // NEC + APPLE          >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL           1       // Samsung + Samsung32  >= 10000                 ~300 bytes
#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL        1       // Matsushita           >= 10000                  ~50 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL          1       // Kaseikyo             >= 10000                 ~250 bytes

// more protocols, enable here!                 Enable  Remarks                 F_INTERRUPTS            Program Space
#define IRMP_SUPPORT_DENON_PROTOCOL             0       // DENON, Sharp         >= 10000                 ~250 bytes
#define IRMP_SUPPORT_RC5_PROTOCOL               0       // RC5                  >= 10000                 ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL               0       // RC6 & RC6A           >= 10000                 ~250 bytes
#define IRMP_SUPPORT_JVC_PROTOCOL               0       // JVC                  >= 10000                 ~150 bytes
#define IRMP_SUPPORT_NEC16_PROTOCOL             0       // NEC16                >= 10000                 ~100 bytes
#define IRMP_SUPPORT_NEC42_PROTOCOL             0       // NEC42                >= 10000                 ~300 bytes
#define IRMP_SUPPORT_IR60_PROTOCOL              0       // IR60 (SDA2008)       >= 10000                 ~300 bytes
#define IRMP_SUPPORT_GRUNDIG_PROTOCOL           0       // Grundig              >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SIEMENS_PROTOCOL           0       // Siemens Gigaset      >= 15000                 ~550 bytes
#define IRMP_SUPPORT_NOKIA_PROTOCOL             0       // Nokia                >= 10000                 ~300 bytes

// exotic protocols, enable here!               Enable  Remarks                 F_INTERRUPTS            Program Space
#define IRMP_SUPPORT_BOSE_PROTOCOL              0       // BOSE                 >= 10000                 ~150 bytes
#define IRMP_SUPPORT_KATHREIN_PROTOCOL          0       // Kathrein             >= 10000                 ~200 bytes
#define IRMP_SUPPORT_NUBERT_PROTOCOL            0       // NUBERT               >= 10000                  ~50 bytes
#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL      0       // Bang & Olufsen       >= 10000                 ~200 bytes
#define IRMP_SUPPORT_RECS80_PROTOCOL            0       // RECS80 (SAA3004)     >= 15000                  ~50 bytes
#define IRMP_SUPPORT_RECS80EXT_PROTOCOL         0       // RECS80EXT (SAA3008)  >= 15000                  ~50 bytes
#define IRMP_SUPPORT_THOMSON_PROTOCOL           0       // Thomson              >= 10000                 ~250 bytes
#define IRMP_SUPPORT_NIKON_PROTOCOL             0       // NIKON camera         >= 10000                 ~250 bytes
#define IRMP_SUPPORT_NETBOX_PROTOCOL            0       // Netbox keyboard      >= 10000                 ~400 bytes (PROTOTYPE!)
#define IRMP_SUPPORT_ORTEK_PROTOCOL             0       // ORTEK (Hama)         >= 10000                 ~150 bytes
#define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL        0       // Telefunken 1560      >= 10000                 ~150 bytes
#define IRMP_SUPPORT_FDC_PROTOCOL               0       // FDC3402 keyboard     >= 10000 (better 15000)  ~150 bytes (~400 in combination with RC5)
#define IRMP_SUPPORT_RCCAR_PROTOCOL             0       // RC Car               >= 10000 (better 15000)  ~150 bytes (~500 in combination with RC5)
#define IRMP_SUPPORT_ROOMBA_PROTOCOL            0       // iRobot Roomba        >= 10000                 ~150 bytes
#define IRMP_SUPPORT_RUWIDO_PROTOCOL            0       // RUWIDO, T-Home       >= 15000                 ~550 bytes
#define IRMP_SUPPORT_A1TVBOX_PROTOCOL           0       // A1 TV BOX            >= 15000 (better 20000)  ~300 bytes
#define IRMP_SUPPORT_LEGO_PROTOCOL              0       // LEGO Power RC        >= 20000                 ~150 bytes
#define IRMP_SUPPORT_RCMM_PROTOCOL              0       // RCMM 12,24, or 32    >= 20000                 ~150 bytes

Each IRMP supported IR protocol consumes the noted amount of code. Here you can apply optimizations: for example the modulation frequency of 455 kHz for the B&O protocol is far away from the frequencies that are used by other protocols. Maybe you need a different IR receiver, otherwise you could disable these protocols. For example you cannot receive a B&O protocol (455kHz) with a TSOP1738 / TSOP 31238.

Furthermore the protocols SIEMENS/FDC/RCCAR are only reliable detected at a frequency starting at 15 kHz. For LEGO it is even 20 kHz. When you want to use these protocols, you must adjust F_INTERRUPTS. Otherwise, during compilation you will get a warning and the corresponding protocols are automatically disabled.

IRMP_PORT_LETTER + IRMP_BIT_NUMBER

This constant defines the pin where the IR receiver is connected.

Default value is PORT B6:

/*---------------------------------------------------------------------------
 * Change hardware pin here for ATMEL AVR
 *---------------------------------------------------------------------------
 */
#if defined (ATMEL_AVR)                         // use PB6 as IR input on AVR
#  define IRMP_PORT_LETTER                      B
#  define IRMP_BIT_NUMBER                       6

These two values must match your hardware configuration.

This applies also to STM32 MCUs:

/*----------------------------------------------------------------------------
 * Change hardware pin here for ARM STM32
 *----------------------------------------------------------------------------
 */
#elif defined (ARM_STM32)                       // use C13 as IR input on STM32
#  define IRMP_PORT_LETTER                      C
#  define IRMP_BIT_NUMBER                       13

And the corresponding section for STM8 MCUs:

/*----------------------------------------------------------------------------
 * Change hardware pin here for STM8
 *----------------------------------------------------------------------------
 */
#elif defined (SDCC_STM8)                       // use PA1 as IR input on STM8
#  define IRMP_PORT_LETTER                      A
#  define IRMP_BIT_NUMBER                       1

For PIC controllers there is only the define for IRMP_PIN - depending on compiler:

/*----------------------------------------------------------------------------
 * Change hardware pin here for PIC C18 compiler
 *----------------------------------------------------------------------------
 */
#elif defined (PIC_C18)                         // use RB4 as IR input on PIC
#  define IRMP_PIN                              PORTBbits.RB4

/*----------------------------------------------------------------------------
 * Change hardware pin here for PIC CCS compiler
 *----------------------------------------------------------------------------
 */
#elif defined (PIC_CCS)                         // use PB4 as IR input on PIC
#  define IRMP_PIN                              PIN_B4

IRMP_USE_CALLBACK

Default value:

#define IRMP_USE_CALLBACK                      0        // flag: 0 = don't use callbacks, 1 = use callbacks, default is 0

When you turn on callbacks, on any level change at the input the callback function is called. This could be use to visualize incoming IR signals by driving another output pin.

Here is an example:

#define LED_PORT PORTD                                  // LED at PD6
#define LED_DDR  DDRD
#define LED_PIN  6

/*-----------------------------------------------------------------------------------------------------------------------
 * Called (back) from IRMP module
 * This example switches a LED (which is connected to Vcc)
 *-----------------------------------------------------------------------------------------------------------------------
 */
void
led_callback (uint8_t on)
{
    if (on)
    {
       LED_PORT &= ~(1 << LED_PIN);
    }
    else
    {
       LED_PORT |= (1 << LED_PIN);
    }
}

int
main ()
{
    ...
    irmp_init ();

    LED_DDR |= (1 << LED_PIN);         // LED pin to output
    LED_PORT |= (1 << LED_PIN);        // switch LED off (active low)
    irmp_set_callback_ptr (led_callback);

    sei ();
    ...
}

IRMP_LOGGING

With IRMP_LOGGING the logging of received IR frames can be turned on.

Default value:

#define IRMP_LOGGING                            0       // 1: log IR signal (scan), 0: do not. default is 0

Further documentation can be found here: Scanning of unknown IR Protocols.

IRMP in Practice

The IRMP supported protocols use partly variable, partly fixed bit length from 2 up to 48 bits. These will be described by preprocessor defines.

IRMP separates these IR frames always into 3 sections:

1. protocol ID
2. address or vendorcode
3. command

with this function

  irmp_get_data (IRMP_DATA * irmp_data_p)

you can recall a decoded message. The return value is 1 when a message has been received, otherwise it is 0. In the first case the struct members

    irmp_data_p->protocol (8 Bit)
    irmp_data_p->address (16 Bit)
    irmp_data_p->command (16 Bit)
    irmp_data_p->flags (8 Bit)

contain valid information.

That means: finally you'll get simply three values (protocol, address and command) that can be checked with an if or switch statement. Here is a sample decoder which checks for key 1-9 on a remote:

   IRMP_DATA irmp_data;

   if (irmp_get_data (&irmp_data))
   {
      if (irmp_data.protocol == IRMP_NEC_PROTOCOL &&     // NEC-Protokoll
          irmp_data.address == 0x1234)                   // Adresse 0x1234
      {
         switch (irmp_data.command)
         {
            case 0x0001: key1_pressed(); break;          // Taste 1
            case 0x0002: key2_pressed(); break;          // Taste 2
            ...
            case 0x0009: key9_pressed(); break;          // Taste 9
         }
      }
   }

Here are possible constants for irmp_data.protocol, see also irmpprotocols.h:

#define IRMP_SIRCS_PROTOCOL                      1              // Sony
#define IRMP_NEC_PROTOCOL                        2              // NEC, Pioneer, JVC, Toshiba, NoName etc.
#define IRMP_SAMSUNG_PROTOCOL                    3              // Samsung
#define IRMP_MATSUSHITA_PROTOCOL                 4              // Matsushita
#define IRMP_KASEIKYO_PROTOCOL                   5              // Kaseikyo (Panasonic etc)
#define IRMP_RECS80_PROTOCOL                     6              // Philips, Thomson, Nordmende, Telefunken, Saba
#define IRMP_RC5_PROTOCOL                        7              // Philips etc
#define IRMP_DENON_PROTOCOL                      8              // Denon, Sharp
#define IRMP_RC6_PROTOCOL                        9              // Philips etc
#define IRMP_SAMSUNG32_PROTOCOL                 10              // Samsung32: no sync pulse at bit 16, length 32 instead of 37
#define IRMP_APPLE_PROTOCOL                     11              // Apple, very similar to NEC
#define IRMP_RECS80EXT_PROTOCOL                 12              // Philips, Technisat, Thomson, Nordmende, Telefunken, Saba
#define IRMP_NUBERT_PROTOCOL                    13              // Nubert
#define IRMP_BANG_OLUFSEN_PROTOCOL              14              // Bang & Olufsen
#define IRMP_GRUNDIG_PROTOCOL                   15              // Grundig
#define IRMP_NOKIA_PROTOCOL                     16              // Nokia
#define IRMP_SIEMENS_PROTOCOL                   17              // Siemens, e.g. Gigaset
#define IRMP_FDC_PROTOCOL                       18              // FDC keyboard
#define IRMP_RCCAR_PROTOCOL                     19              // RC Car
#define IRMP_JVC_PROTOCOL                       20              // JVC (NEC with 16 bits)
#define IRMP_RC6A_PROTOCOL                      21              // RC6A, e.g. Kathrein, XBOX
#define IRMP_NIKON_PROTOCOL                     22              // Nikon
#define IRMP_RUWIDO_PROTOCOL                    23              // Ruwido, e.g. T-Home Mediareceiver
#define IRMP_IR60_PROTOCOL                      24              // IR60 (SDA2008)
#define IRMP_KATHREIN_PROTOCOL                  25              // Kathrein
#define IRMP_NETBOX_PROTOCOL                    26              // Netbox keyboard (bitserial)
#define IRMP_NEC16_PROTOCOL                     27              // NEC with 16 bits (incl. sync)
#define IRMP_NEC42_PROTOCOL                     28              // NEC with 42 bits
#define IRMP_LEGO_PROTOCOL                      29              // LEGO Power Functions RC
#define IRMP_THOMSON_PROTOCOL                   30              // Thomson
#define IRMP_BOSE_PROTOCOL                      31              // BOSE
#define IRMP_A1TVBOX_PROTOCOL                   32              // A1 TV Box
#define IRMP_ORTEK_PROTOCOL                     33              // ORTEK - Hama
#define IRMP_TELEFUNKEN_PROTOCOL                34              // Telefunken (1560)
#define IRMP_ROOMBA_PROTOCOL                    35              // iRobot Roomba vacuum cleaner
#define IRMP_RCMM32_PROTOCOL                    36              // Fujitsu-Siemens (Activy remote control)
#define IRMP_RCMM24_PROTOCOL                    37              // Fujitsu-Siemens (Activy keyboard)
#define IRMP_RCMM12_PROTOCOL                    38              // Fujitsu-Siemens (Activy keyboard)
#define IRMP_SPEAKER_PROTOCOL                   39              // Another loudspeaker protocol, similar to Nubert
#define IRMP_LGAIR_PROTOCOL                     40              // LG air conditioner
#define IRMP_SAMSUNG48_PROTOCOL                 41              // air conditioner with SAMSUNG protocol (48 bits)
#define IRMP_MERLIN_PROTOCOL                    42              // Merlin (Pollin 620 185)
#define IRMP_PENTAX_PROTOCOL                    43              // Pentax camera
#define IRMP_FAN_PROTOCOL                       44              // FAN (ventilator), very similar to NUBERT, but last bit is data bit instead of stop bit
#define IRMP_S100_PROTOCOL                      45              // very similar to RC5, but 14 instead of 13 data bits
#define IRMP_ACP24_PROTOCOL                     46              // Stiebel Eltron ACP24 air conditioner
#define IRMP_TECHNICS_PROTOCOL                  47              // Technics, similar to Matsushita, but 22 instead of 24 bits

The values of address and the command code of an unknown remote can be received and printed over UART or LCD. Then these values can be used hard coded in your decoder routine. Or you write a teaching routine, where you need to press a key once to store the code in an EEPROM. A sample for this can be found in Lernfähige IR-Fernbedienung mit IRMP.

Another example main function is included in the zip file, showing also the timer initialization.

"Debouncing" of Keys

To distinguish between long key press or a single press, the bit mask IRMP_FLAG_REPETITION exists. This will be set in struct member flags when a key on the remote is pressed for longer time and therefore the same command is repeated in short periods.

Example:

    if (irmp_data.flags & IRMP_FLAG_REPETITION)
    {
      // long key press
      // either:
      //   ignore the (repeated) key
      // or:
      //   use this information for a repeat function
    }
    else
    {
      // key was pressed again
    }

This could be used to "debounce" the keys 0-9 by ignoring commands with bit IRMP_FLAG_REPETITION set. For keys like ' VOLUME+' or 'VOLUME-' using the repetition could be useful, maybe to fade a LED.

If you want to decode only singe keys, you can reduce the block above:

    if (! (irmp_data.flags & IRMP_FLAG_REPETITION))
    {
      // Its a new key
      // ACTION!
    }

Mode of Operation

The "Working Horse" of IRMP is the interrupt service routine irmp_ISR() which should be called 15000 times per second. Is this rate different, the constant F_INTERRUPTS in irmpconfig.h needs to be adjusted.

irmp_ISR() detects first the length and the form of the startbit(s) and determines the used protocols by this information. As soon as the protocol was identified, the further bits are parameterized to read the following bits most efficient until the IR command is complete.

Just to stop slashers:

I know that the ISR is quite large. But as it acts as a state machine, the effective executed code per cycle is relative small. While it is "dark" (and that is the case for the most time ;-)) the spent time is vanishing short. In the WordClock project for example are called 8 ISR's with the same timer, there is irmp_ISR() only one amongst many others. For at least 8 MHz CPU clock no timing problems occured. Therefor I see really no problem in the length of the ISR.

A crystal is not a neccessary must, it works well with the internal AVR oscillator. Remember to set the correct fuses for the CPU to run at 8 MHz, check irmp-main-avr.c for correct values for an ATMEGA88.

Scanning of unknown IR Protocols

Changing in irmpconfig.h in line

    #define IRMP_LOGGING    0   // 1: log IR signal (scan), 0: do not (default)

the value for IRMP_LOGGING to 1, then a logging in IRMP will be turned on: the bright- and darkphases will be sent via UART with 9600 bit/s: 1=dark, 0=bright. Maybe the constans in the functions uart_init() and uart_putc() must be adjusted, this depends on the used AVR MCU.

Remark: for PIC-processors there is an own logging module named irmpextlog.c. This makes it possible to log via USB. This applies not to the AVR version

If you record these protocol scans with a terminal program and save them as a textfile, you can use these files for analyzing the frames in ordner to add a yet unknown protocol to IRMP - see next chapter.

If you have a remote control that is not supported by IRMP you can send me (ukw) the scan files. Then I can check if the protocol fits into the IRMP concepts and adapt the sources if applicable.

IRMP under Linux and Windows

Compilation

irmp.c can be compiled under Linux for testing IR scans in textfiles. In the subdirectory 'IR-Data' you will find such files that you can use as input files for IRMP.

The compilation of IRMP is started by:

   make -f makefile.lnx

This will generate 3 IRMP versions:

  • irmp-10kHz: Version for 10kHz Scans
  • irmp-15kHz: Version for 15kHz Scans
  • irmp-20kHz: Version for 20kHz Scans

Starting IRMP

The calling syntax is:

 ./irmp-nnkHz [-l|-p|-a|-v] < scan-file

The given options are exclusive, that means only one option per call is valid:

Option:

  -l  List             print a list with pulses and pauses
  -a analyze           analyse the puls/pauses and write a "spectrum" in ASCII format
  -v verbose           verbose output
  -p  Print Timings    print a timing table for all protocols

Samples:

Normal Output

  ./irmp-10kHz < IR-Data/orion_vcr_07660BM070.txt
 -------------------------------------------------------------------------
 # Taste 1
 00000001110111101000000001111111 p =  2, a = 0x7b80, c = 0x0001, f = 0x00
 -------------------------------------------------------------------------
 # Taste 2
 00000001110111100100000010111111 p =  2, a = 0x7b80, c = 0x0002, f = 0x00
 -------------------------------------------------------------------------
 # Taste 3
 00000001110111101100000000111111 p =  2, a = 0x7b80, c = 0x0003, f = 0x00
 -------------------------------------------------------------------------
 # Taste 4
 00000001110111100010000011011111 p =  2, a = 0x7b80, c = 0x0004, f = 0x00
 -------------------------------------------------------------------------
 ...

Output Lists

  ./irmp-10kHz -l < IR-Data/orion_vcr_07660BM070.txt
# Taste 1
pulse: 91 pause: 44
pulse: 6 pause: 5
pulse: 6 pause: 6
pulse: 6 pause: 5
pulse: 6 pause: 5
pulse: 6 pause: 5
pulse: 6 pause: 6
pulse: 6 pause: 5
pulse: 6 pause: 16
...

Analysing

  ./irmp-10kHz -a < IR-Data/orion_vcr_07660BM070.txt
-------------------------------------------------------------------------------
START PULSES:
 90 o 1
 91 oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 33
 92 ooo 2
pulse avg: 91.0=9102.8 us, min: 90=9000.0 us, max: 92=9200.0 us, tol:  1.1%
-------------------------------------------------------------------------------
START PAUSES:
 43 oo 1
 44 oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 25
 45 oooooooooooooooooooooooo 10
pause avg: 44.2=4425.0 us, min: 43=4300.0 us, max: 45=4500.0 us, tol:  2.8%
-------------------------------------------------------------------------------
PULSES:
  5 o 17
  6 ooooooooooooooooooooooooooooooooooooooooooooooooooooooo 562
  7 oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 609
pulse avg:  6.5= 649.8 us, min:  5= 500.0 us, max:  7= 700.0 us, tol: 23.1%
-------------------------------------------------------------------------------
PAUSES:
  4 ooooooooooooooooooooooo 169
  5 oooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 412
  6 oooo 31
pause avg:  4.8= 477.5 us, min:  4= 400.0 us, max:  6= 600.0 us, tol: 25.7%
 15 oooooo 43
 16 oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 425
 17 oooooooooo 72
pause avg: 16.1=1605.4 us, min: 15=1500.0 us, max: 17=1700.0 us, tol:  6.6%
-------------------------------------------------------------------------------

Here you see the measured times of all pulses and pauses as (horizontal) bell shaped curves, which of course are not quite ideal displayed due to the ASCII formatting. The smaller the measured channels, the better is the timing of the remote.

The above output can be read as:

  • the start bit has a pulse length between 9000 and 9200 µs, in average 9102 µs. The deviation from this average is about 1.1 %
  • the start bit has a pause length between 4300 and 4500 µs, the average is 4424 µs. The error is about 2.8 %.
  • the pulse length of a databit is between 500 and 700 µs, in average 650 µs, the error is (quite large!) 23.1 %

Further there are two more pauses with different length (for bits 0 and 1). Checking this I leave to the willing reader ;-)

Verbose Output

   ./irmp-10kHz -v < IR-Data/orion_vcr_07660BM070.txt
-------------------------------------------------------------------------------
# 1 - IR-cmd: 0x0001
   0.200ms [starting pulse]
  13.700ms [start-bit: pulse = 91, pause = 44]
protocol = NEC, start bit timings: pulse:  62 - 118, pause:  30 -  60
pulse_1:   3 -   8
pause_1:  11 -  23
pulse_0:   3 -   8
pause_0:   3 -   8
command_offset: 16
command_len:     16
complete_len:    32
stop_bit:         1
  14.800ms [bit  0: pulse =   6, pause =   5] 0
  16.000ms [bit  1: pulse =   6, pause =   6] 0
  17.100ms [bit  2: pulse =   6, pause =   5] 0
  18.200ms [bit  3: pulse =   6, pause =   5] 0
  19.300ms [bit  4: pulse =   6, pause =   5] 0
  20.500ms [bit  5: pulse =   6, pause =   6] 0
  21.600ms [bit  6: pulse =   6, pause =   5] 0
  23.800ms [bit  7: pulse =   6, pause =  16] 1
  26.100ms [bit  8: pulse =   6, pause =  17] 1
  28.300ms [bit  9: pulse =   6, pause =  16] 1
  29.500ms [bit 10: pulse =   6, pause =   6] 0
  31.700ms [bit 11: pulse =   6, pause =  16] 1
  34.000ms [bit 12: pulse =   6, pause =  17] 1
  36.200ms [bit 13: pulse =   6, pause =  16] 1
  38.500ms [bit 14: pulse =   6, pause =  17] 1
  39.600ms [bit 15: pulse =   6, pause =   5] 0
  41.900ms [bit 16: pulse =   6, pause =  17] 1
  43.000ms [bit 17: pulse =   6, pause =   5] 0
  44.100ms [bit 18: pulse =   6, pause =   5] 0
  45.200ms [bit 19: pulse =   6, pause =   5] 0
  46.400ms [bit 20: pulse =   7, pause =   5] 0
  47.500ms [bit 21: pulse =   6, pause =   5] 0
  48.600ms [bit 22: pulse =   6, pause =   5] 0
  49.800ms [bit 23: pulse =   6, pause =   6] 0
  50.900ms [bit 24: pulse =   5, pause =   6] 0
  53.100ms [bit 25: pulse =   6, pause =  16] 1
  55.400ms [bit 26: pulse =   6, pause =  17] 1
  57.600ms [bit 27: pulse =   6, pause =  16] 1
  59.900ms [bit 28: pulse =   6, pause =  17] 1
  62.100ms [bit 29: pulse =   6, pause =  16] 1
  64.400ms [bit 30: pulse =   6, pause =  17] 1
  66.700ms [bit 31: pulse =   6, pause =  17] 1
stop bit detected
  67.300ms code detected, length = 32
  67.300ms p =  2, a = 0x7b80, c = 0x0001, f = 0x00
-------------------------------------------------------------------------------

Starting under Windows

IRMP can be used as well under Windows, like:

  • start command line console
  • change to directory 'irmp'
  • enter:
           irmp-10kHz.exe < IR-Data\rc5x.txt

The same options apply as for the Linux version.

Long Outputs

As some outputs are pretty large, it is recommended to redirect the output to a file or filter for paging:

Linux:

           ./irmp-10kHz < IR-Data/rc5x.txt | less

Windows:

           irmp-10kHz.exe < IR-Data\rc5x.txt | more

Remote Controls

Protocol Name Device Device Address
NEC Toshiba CT-9859 Fernseher 0x5F40
Toshiba VT-728G V-728G Videorekorder 0x5B44
Elta 8848 MP 4 DVD-Player 0x7F00
AS-218 Askey TV-View CHP03X (TV-Karte) 0x3B86
Cyberhome ??? Cyberhome DVD Player 0x6D72
WD TV Live Western Digital Multimediaplayer 0x1F30
Canon WL-DC100 Kamera Canon PowerShot G5 0xB1CA
NEC16 Daewoo Videorekorder 0x0015
KASEIKYO Technics EUR646497 AV Receiver SA-AX 730 0x2002
Panasonic TV Fernseher TX-L32EW6 0x2002
RC5 Loewe Assist/RC3/RC4 Fernseher (FB auf TV-Mode) 0x0000
RC6 Philips Television Fernseher (FB auf TV-Mode) 0x0000
SIRCS Sony RM-816 Fernseher (FB auf TV-Mode) 0x0000
DENON DENON RC970 AVR3805 (Verstärker) 0x0008
DENON RC970 DVD/CD-Player 0x0002
DENON RC970 Tuner 0x0006
SAMSUNG32 Samsung AA59-00484A LE40D550 Fernseher 0x0707
LG AKB72033901 Blu-Ray Player BD370 0x2D2D
APPLE Apple Apple Dock (iPod 2) 0x0020

Cameras

Pentax-Protokoll

IRMP supports more and more also camera remotes like:

The command variety isn't really large. Usually the cameras understand only the command: "Trigger".

Here is a short table for PENTAX cameras:

Command Function
0x0000 Trigger
0x0001 change Zoomlevel

Because there is no address designated in the PENTAX-protocol, this should be set for sending in IRSND to 0x0000. You should also use a crystal in this case because especially the Nikons are very fussy regarding the timing.

IR Keyboards

FDC-3402-keyboard

IRMP supports from version 1.7.0 also IR keyboards, namely the FDC-3402 from www.pollin.de (partno. 711 056) for less than 2 Euro. (not available as of 19.09.2017 )

On detection of a key press the following data is returned:

Protocol-Number  (irmp_data.protocol): 18
Address          (irmp_data.address) : 0x003F

As command (irmp_data.command) the following values are returned:

Code Key Code Key Code Key Code Key Code Key Code Key Code Key Code Key
0x0000 0x0010 TAB 0x0020 's' 0x0030 'c' 0x0040 0x0050 HOME 0x0060 0x0070 MENUE
0x0001 '^' 0x0011 'q' 0x0021 'd' 0x0031 'v' 0x0041 0x0051 END 0x0061 0x0071 BACK
0x0002 '1' 0x0012 'w' 0x0022 'f' 0x0032 'b' 0x0042 0x0052 0x0062 0x0072 FORWARD
0x0003 '2' 0x0013 'e' 0x0023 'g' 0x0033 'n' 0x0043 0x0053 UP 0x0063 0x0073 ADDRESS
0x0004 '3' 0x0014 'r' 0x0024 'h' 0x0034 'm' 0x0044 0x0054 DOWN 0x0064 0x0074 WINDOW
0x0005 '4' 0x0015 't' 0x0025 'j' 0x0035 ',' 0x0045 0x0055 PAGE_UP 0x0065 0x0075 1ST_PAGE
0x0006 '5' 0x0016 'z' 0x0026 'k' 0x0036 '.' 0x0046 0x0056 PAGE_DOWN 0x0066 0x0076 STOP
0x0007 '6' 0x0017 'u' 0x0027 'l' 0x0037 '-' 0x0047 0x0057 0x0067 0x0077 MAIL
0x0008 '7' 0x0018 'i' 0x0028 'ö' 0x0038 0x0048 0x0058 0x0068 0x0078 FAVORITES
0x0009 '8' 0x0019 'o' 0x0029 'ä' 0x0039 SHIFT_RIGHT 0x0049 0x0059 RIGHT 0x0069 0x0079 NEW_PAGE
0x000A '9' 0x001A 'p' 0x002A '#' 0x003A CTRL 0x004A 0x005A 0x006A 0x007A SETUP
0x000B '0' 0x001B 'ü' 0x002B CR 0x003B 0x004B INSERT 0x005B 0x006B 0x007B FONT
0x000C 'ß' 0x001C '+' 0x002C SHIFT_LEFT 0x003C ALT_LEFT 0x004C DELETE 0x005C 0x006C 0x007C PRINT
0x000D '´' 0x001D 0x002D '<' 0x003D SPACE 0x004D 0x005D 0x006D 0x007D
0x000E 0x001E CAPSLOCK 0x002E 'y' 0x003E ALT_RIGHT 0x004E 0x005E 0x006E ESCAPE 0x007E ON_OFF
0x000F BACKSPACE 0x001F 'a' 0x002F 'x' 0x003F 0x004F LEFT 0x005F 0x006F 0x007F

Special keys left side:

Code Key
0x0400 KEY_MOUSE_1
0x0800 KEY_MOUSE_2

The above values are for pressing a key. On release, IRMP sets also Bit 8 (0x80) in the command.

Example:

     Key 'a' pressed:   0x001F
     Key 'a' released:  0x009F

Exception for the ON / OFF key: This one sends only for key press a code, not for release.

Is a key pressed for a longer time, it will be notified in irmp_data.flag

Example:

                          command   flag
     Key 'a' pressed:   0x001F    0x00
     Key 'a' pressed:   0x001F    0x01
     Key 'a' pressed:   0x001F    0x01
     Key 'a' pressed:   0x001F    0x01
     ....
     Key 'a' released:  0x009F    0x00


When key combinations (like a capital 'A') are pressed, then the return values are a sequence like this:

     Left SHIFT-key pressed:    0x0002
     Key 'a' pressed:           0x001F
     Key 'a' released:          0x009F
     Left SHIFT-key released:   0x0082

In irmp.c you will find a function get_fdc_key() for the Linux version, which can be used as a template to convert the FDC keycodes into the corresponding ASCII codes. This function can be used either local on the MCU to decode the keycodes, or on the hostsystem (e.g. PC) where the IRMP data structure is sent to. Therefore the function incl. preprocessor constands should be copied to your application code.

Here is an excerpt:

#define STATE_LEFT_SHIFT    0x01
#define STATE_RIGHT_SHIFT   0x02
#define STATE_LEFT_CTRL     0x04
#define STATE_LEFT_ALT      0x08
#define STATE_RIGHT_ALT     0x10

#define KEY_ESCAPE          0x1B            // keycode = 0x006e
#define KEY_MENUE           0x80            // keycode = 0x0070
#define KEY_BACK            0x81            // keycode = 0x0071
#define KEY_FORWARD         0x82            // keycode = 0x0072
#define KEY_ADDRESS         0x83            // keycode = 0x0073
#define KEY_WINDOW          0x84            // keycode = 0x0074
#define KEY_1ST_PAGE        0x85            // keycode = 0x0075
#define KEY_STOP            0x86            // keycode = 0x0076
#define KEY_MAIL            0x87            // keycode = 0x0077
#define KEY_FAVORITES       0x88            // keycode = 0x0078
#define KEY_NEW_PAGE        0x89            // keycode = 0x0079
#define KEY_SETUP           0x8A            // keycode = 0x007a
#define KEY_FONT            0x8B            // keycode = 0x007b
#define KEY_PRINT           0x8C            // keycode = 0x007c
#define KEY_ON_OFF          0x8E            // keycode = 0x007c

#define KEY_INSERT          0x90            // keycode = 0x004b
#define KEY_DELETE          0x91            // keycode = 0x004c
#define KEY_LEFT            0x92            // keycode = 0x004f
#define KEY_HOME            0x93            // keycode = 0x0050
#define KEY_END             0x94            // keycode = 0x0051
#define KEY_UP              0x95            // keycode = 0x0053
#define KEY_DOWN            0x96            // keycode = 0x0054
#define KEY_PAGE_UP         0x97            // keycode = 0x0055
#define KEY_PAGE_DOWN       0x98            // keycode = 0x0056
#define KEY_RIGHT           0x99            // keycode = 0x0059
#define KEY_MOUSE_1         0x9E            // keycode = 0x0400
#define KEY_MOUSE_2         0x9F            // keycode = 0x0800

static uint8_t
get_fdc_key (uint16_t cmd)
{
    static uint8_t key_table[128] =
    {
     // 0     1    2    3    4    5    6    7    8     9     A     B     C     D    E    F
         0,   '^', '1', '2', '3', '4', '5', '6', '7',  '8',  '9',  '0',  0xDF, '´', 0,   '\b',
        '\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',  'o',  'p',  0xFC, '+',  0,   0,   'a',
        's',  'd', 'f', 'g', 'h', 'j', 'k', 'l', 0xF6, 0xE4, '#',  '\r', 0,    '<', 'y', 'x',
        'c',  'v', 'b', 'n', 'm', ',', '.', '-', 0,    0,    0,    0,    0,    ' ', 0,   0,
 
         0,   '°', '!', '"', '§', '$', '%', '&', '/',  '(',  ')',  '=',  '?',  '`', 0,   '\b',
        '\t', 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',  'O',  'P',  0xDC, '*',  0,   0,   'A',
        'S',  'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xD6, 0xC4, '\'', '\r', 0,    '>', 'Y', 'X',
        'C',  'V', 'B', 'N', 'M', ';', ':', '_', 0,    0,    0,    0,    0,    ' ', 0,   0
    };
    static uint8_t state;

    uint8_t key = 0;

    switch (cmd)
    {
        case 0x002C: state |=  STATE_LEFT_SHIFT;    break;              // pressed left shift
        case 0x00AC: state &= ~STATE_LEFT_SHIFT;    break;              // released left shift
        case 0x0039: state |=  STATE_RIGHT_SHIFT;   break;              // pressed right shift
        case 0x00B9: state &= ~STATE_RIGHT_SHIFT;   break;              // released right shift
        case 0x003A: state |=  STATE_LEFT_CTRL;     break;              // pressed left ctrl
        case 0x00BA: state &= ~STATE_LEFT_CTRL;     break;              // released left ctrl
        case 0x003C: state |=  STATE_LEFT_ALT;      break;              // pressed left alt
        case 0x00BC: state &= ~STATE_LEFT_ALT;      break;              // released left alt
        case 0x003E: state |=  STATE_RIGHT_ALT;     break;              // pressed left alt
        case 0x00BE: state &= ~STATE_RIGHT_ALT;     break;              // released left alt

        case 0x006e: key = KEY_ESCAPE;              break;
        case 0x004b: key = KEY_INSERT;              break;
        case 0x004c: key = KEY_DELETE;              break;
        case 0x004f: key = KEY_LEFT;                break;
        case 0x0050: key = KEY_HOME;                break;
        case 0x0051: key = KEY_END;                 break;
        case 0x0053: key = KEY_UP;                  break;
        case 0x0054: key = KEY_DOWN;                break;
        case 0x0055: key = KEY_PAGE_UP;             break;
        case 0x0056: key = KEY_PAGE_DOWN;           break;
        case 0x0059: key = KEY_RIGHT;               break;
        case 0x0400: key = KEY_MOUSE_1;             break;
        case 0x0800: key = KEY_MOUSE_2;             break;

        default:
        {
            if (!(cmd & 0x80))                      // pressed key
            {
                if (cmd >= 0x70 && cmd <= 0x7F)     // function keys
                {
                    key = cmd + 0x10;               // 7x -> 8x
                }
                else if (cmd < 64)                  // key listed in key_table
                {
                    if (state & (STATE_LEFT_ALT | STATE_RIGHT_ALT))
                    {
                        switch (cmd)
                        {
                            case 0x0003: key = 0xB2;    break; // ²
                            case 0x0008: key = '{';     break;
                            case 0x0009: key = '[';     break;
                            case 0x000A: key = ']';     break;
                            case 0x000B: key = '}';     break;
                            case 0x000C: key = '\\';    break;
                            case 0x001C: key = '~';     break;
                            case 0x002D: key = '|';     break;
                            case 0x0034: key = 0xB5;    break; // µ
                        }
                    }
                    else if (state & (STATE_LEFT_CTRL))
                    {
                        if (key_table[cmd] >= 'a' && key_table[cmd] <= 'z')
                        {
                            key = key_table[cmd] - 'a' + 1;
                        }
                        else
                        {
                            key = key_table[cmd];
                        }
                    }
                    else
                    {
                        int idx = cmd + ((state & (STATE_LEFT_SHIFT | STATE_RIGHT_SHIFT)) ? 64 : 0);

                        if (key_table[idx])
                        {
                            key = key_table[idx];
                        }
                    }
                }
            }
            break;
        }
    }

    return (key);
}

And at least an example for the usage of function get_fdc_key():

    if (irmp_get_data (&irmp_data))
    {
        uint8_t key;

        if (irmp_data.protocol == IRMP_FDC_PROTOCOL &&
            (key = get_fdc_key (irmp_data.command)) != 0)
        {
            if ((key >= 0x20 && key < 0x7F) || key >= 0xA0) // show only printable characters
            {
                printf ("ascii-code = 0x%02x, character = '%c'\n", key, key);
            }
            else // it's a non-printable key
            {
                printf ("ascii-code = 0x%02x\n", key);
            }
        }
    }

All non-printable characters are coded as:

Key Constant Value
ESC KEY_ESCAPE 0x1B
Menu KEY_MENUE 0x80
Back KEY_BACK 0x81
Forward KEY_FORWARD 0x82
Adress KEY_ADDRESS 0x83
Window KEY_WINDOW 0x84
1. Page KEY_1ST_PAGE 0x85
Stop KEY_STOP 0x86
Mail KEY_MAIL 0x87
Fav. KEY_FAVORITES 0x88
New Page KEY_NEW_PAGE 0x89
Setup KEY_SETUP 0x8A
Font KEY_FONT 0x8B
Print KEY_PRINT 0x8C
On/Off KEY_ON_OFF 0x8E
Backspace '\b' 0x08
CR/ENTER '\r' 0x0C
TAB '\t' 0x09
Insert KEY_INSERT 0x90
Delete KEY_DELETE 0x91
Cursor left KEY_LEFT 0x92
Pos1 KEY_HOME 0x93
End KEY_END 0x94
Cursor right KEY_UP 0x95
Cursor down KEY_DOWN 0x96
Page up KEY_PAGE_UP 0x97
Page down KEY_PAGE_DOWN 0x98
Cursor left KEY_RIGHT 0x99
Left Mousebutton KEY_MOUSE_1 0x9E
Right Mousebutton KEY_MOUSE_2 0x9F

The function get_fdc_key() considers the holding of key pressed of Shift-, Ctrl- and ALT. For this reason not only the writing of capital letters works, but also the selection of special characters with the key combination ALT + key, e.g. ALT + m -> µ or ALT + q -> @. Also you can send CTRL-A to CTRL-Z by using the Ctrl key. The Caps Lock key is ignored, as I regard this key as the most unnecessary key at all ;-)

Appendix

IR Protocols in Detail

Pulse Distance Coding

Pulse Distance Protocols

 

NEC + extended NEC

NEC + extended NEC Value
Frequency 36 kHz / 38 kHz
Coding pulse distance
Frame 1 start bit + 32 data bits + 1 stop bit
Data NEC 8 address bits + 8 inverted address bits + 8 command bits + 8 inverted command bits
Data ext. NEC 16 address bits + 8 command bits + 8 inverted command bits
Start Bit 9000µs pulse, 4500µs pause
0 Bit 560µs pulse, 560µs pause
1 Bit 560µs pulse, 1690µs pause
Stop Bit 560µs pulse
Repetition none
Keyboard Repetition 9000µs pulse, 2250µs pause, 560µs pulse, ~100ms pause
Bit Order LSB first

JVC

JVC Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 16 data bits + 1 stop bit
Data 4 address bits + 12 command bits
Start Bit 9000µs pulse, 4500µs pause, 6000µs pause if keyboard repetition
0 Bit 560µs pulse, 560µs pause
1 Bit 560µs pulse, 1690µs pause
Stop Bit 560µs pulse
Repetition none
Keyboard Repetition after pause of 25ms
Bit Order LSB first

NEC16

NEC16 Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 8 address bits + 1 sync bit + 8 data bits + 1 stop bit
Start Bit 9000µs pulse, 4500µs pause
sync bit 560µs pulse, 4500µs pause
0 Bit 560µs pulse, 560µs pause
1 Bit 560µs pulse, 1690µs pause
Stop Bit 560µs pulse
Repetition none
Keyboard Repetition after pause of 25ms?
Bit Order LSB first

NEC42

NEC42 Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 42 data bits + 1 stop bit
Data 13 address bits + 13 inverted address bits + 8 command bits + 8 inverted command bits
Start Bit 9000µs pulse, 4500µs pause
0 Bit 560µs pulse, 560µs pause
1 Bit 560µs pulse, 1690µs pause
Stop Bit 560µs pulse
Repetition none
Keyboard Repetition after 110ms (beginning from start bit), 9000µs pulse, 2250µs pause, 560µs pulse
Bit Order LSB first

ACP24

ACP24 Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 70 data bits + 1 stop bit
Data 0 address bits + 70 command bits
Start Bit 390µs pulse, 950µs pause
0 Bit 390µs pulse, 950µs pause
1 Bit 390µs pulse, 13000µs pause
Stop Bit 390µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order MSB first

LGAIR

LGAIR Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 28 data bits + 1 stop bit
Data 8 address bits + 16 command bits + 4 checksum bits
Start Bit 9000µs pulse, 4500µs pause (identical with NEC)
0 Bit 560µs pulse, 560µs pause (identical with NEC)
1 Bit 560µs pulse, 1690µs pause (identical with NEC)
Stop Bit 560µs pulse (identical with NEC)
Repetition none
Keyboard Repetition unknown
Bit Order MSB first (differing to NEC)

SAMSUNG

SAMSUNG Value
Frequency  ?? kHz
Coding pulse distance
Frame 1 start bit + 16 data(1) bits + 1 sync bit + 20 data(2)-bits + 1 stop bit
Data(1) 16 address bits
Data(2) 4 ID bits + 8 command bits + 8 inverted command bits
Start Bit 4500µs pulse, 4500µs pause
0 Bit 550µs pulse, 550µs pause
1 Bit 550µs pulse, 1650µs pause
sync bit 550µs pulse, 4500µs pause
Stop Bit 550µs pulse
Repetition none
Keyboard Repetition repetition after approx. 100ms
Bit Order LSB first

SAMSUNG32

SAMSUNG32 Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 32 data bits + 1 stop bit
Data 16 address bits + 16 command bits
Start Bit 4500µs pulse, 4500µs pause
0 Bit 550µs pulse, 550µs pause
1 Bit 550µs pulse, 1650µs pause
Stop Bit 550µs pulse
Repetition none
Keyboard Repetition Repetition after approx. 47msec
Bit Order LSB first

SAMSUNG48

SAMSUNG48 Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 48 data bits + 1 stop bit
Data 16 address bits + 32 command bits
Command 8 Bits + 8 inverted Bits + 8 Bits + 8 inverted Bits
Start Bit 4500µs pulse, 4500µs pause
0 Bit 550µs pulse, 550µs pause
1 Bit 550µs pulse, 1650µs pause
Stop Bit 550µs pulse
Repetition one after approx. 5 msec
Keyboard Repetition after approx. 45 msec
Bit Order LSB first

MATSUSHITA

MATSUSHITA Value
Frequency 36 kHz
Coding pulse distance, Timing identisch mit TECHNICS
Frame 1 start bit + 24 data bits + 1 stop bit
Data 6 customer bits + 6 command bits + 12 address bits
Start Bit 3488µs pulse, 3488µs pause
0 Bit 872µs pulse, 872µs pause
1 Bit 872µs pulse, 2616µs pause
Stop Bit 872µs pulse
Repetition none
Keyboard Repetition after 40ms pause
Bit Order LSB first?

TECHNICS

TECHNICS Value
Frequency 36 kHz?
Coding pulse distance, Timing identisch mit MATSUSHITA
Frame 1 start bit + 22 data bits + 1 stop bit
Data 11 command bits + 11 inverted command bits
Start Bit 3488µs pulse, 3488µs pause
0 Bit 872µs pulse, 872µs pause
1 Bit 872µs pulse, 2616µs pause
Stop Bit 872µs pulse
Repetition none
Keyboard Repetition after 40ms pause
Bit Order LSB first?

KASEIKYO

KASEIKYO Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 48 data bits + 1 stop bit
Data 16 customer bits + 4 parity bits + 4 genre1 bits + 4 genre2 bits + 10 command bits + 2 ID bits + 8 parity bits
Start Bit 3380µs pulse, 1690µs pause
0 Bit 423µs pulse, 423µs pause
1 Bit 423µs pulse, 1269µs pause
Stop Bit 423µs pulse
Repetition none
Keyboard Repetition after approx. 80ms pause
Bit Order LSB first?

RECS80

RECS80 Value
Frequency 38 kHz
Coding pulse distance
Frame 1 Start Bits + 10 data bits + 1 stop bit
Data 1 toggle bit + 3 address bits + 6 command bits
Start Bit 158µs pulse, 7432µs pause
0 Bit 158µs pulse, 4902µs pause
1 Bit 158µs pulse, 7432µs pause
Stop Bit 158µs pulse
Repetition none
Keyboard Repetition after approx. 100ms
Bit Order MSB first

RECS80EXT

RECS80EXT Value
Frequency 38 kHz
Coding pulse distance
Frame 2 Start Bits + 11 data bits + 1 stop bit
Data 1 toggle bit + 4 address bits + 6 command bits
Start Bit 158µs pulse, 3637µs pause
0 Bit 158µs pulse, 4902µs pause
1 Bit 158µs pulse, 7432µs pause
Stop Bit 158µs pulse
Repetition none
Keyboard Repetition after approx. 100ms
Bit Order MSB first

DENON

DENON Value
Frequency 38 kHz (in practice, theoretically: 32 kHz)
Coding pulse distance
Frame 0 Start Bits + 15 data bits + 1 stop bit
Data 5 address bits + 10 command bits
Command 6 data bits + 2 extension bits + 2 data construction bits (normal: 00, inverted: 11)
Start Bit no Start Bit
0 Bit 310µs pulse, 745µs pause (in practice, theoretically: 275µs pulse, 775µs pause)
1 Bit 310µs pulse, 1780µs pause (in practice, theoretically: 275µs pulse, 1900µs pause)
Stop Bit 310µs pulse (310µs pulse, 745µs pause (in practice, theoretically: 275µs pulse)
Repetition after 65ms with inverted command bits (data construction bits = 11)
Keyboard Repetition both frames after 65ms
Bit Order MSB first

APPLE

APPLE Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 32 data bits + 1 stop bit
Data 16 address bits + 11100000 + 8 command bits
Start Bit see NEC
0 Bit see NEC
1 Bit see NEC
Stop Bit see NEC
Repetition none
Keyboard Repetition after approx. 100ms
Bit Order LSB first

BOSE

BOSE Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 16 data bits + 1 stop bit
Data 0 address bits + 8 command bits + 8 inverted command bits
Start Bit 1060µs pulse, 1425µs pause
0 Bit 550µs pulse, 437µs pause
1 Bit 550µs pulse, 1425µs pause
Stop Bit 550µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order LSB first

B&O

B&O Value
Frequency 455 kHz
Coding pulse distance
Frame 4 start bits + 16 data bits + 1 trailer bit + 1 stop bit
Data 0 address bits + 16 command bits
Start Bit 1 200µs pulse, 2925µs pause
Start Bit 2 200µs pulse, 2925µs pause
Start Bit 3 200µs pulse, 15425µs pause
Start Bit 4 200µs pulse, 2925µs pause
0 Bit 200µs pulse, 2925µs pause
1 Bit 200µs pulse, 9175µs pause
R Bit 200µs pulse, 6050µs pause, repeats the last bit
Trailer Bit 200µs pulse, 12300µs pause
Stop Bit 200µs pulse
Repetition none
Keyboard Repetition after approx. 100ms
Bit Order MSB first

FDC

FDC Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 40 data bits + 1 stop bit
Data 8 address bits + 12 x 0 Bits + 4 press/release bits + 8 command bits + 8 inverted command bits
Start Bit 2085µs pulse, 966µs pause
0 Bit 300µs pulse, 220µs pause
1 Bit 300µs pulse, 715µs pause
Stop Bit 300µs pulse
Repetition none
Press Key press/release bits = 0000
Release Key press/release bits = 1111
Keyboard Repetition after pause of approx. 60ms
Bit Order LSB first

NIKON

NIKON Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 2 data bits + 1 stop bit
Data 2 command bits
Start Bit 2200µs pulse, 27100µs pause
0 Bit 500µs pulse, 1500µs pause
1 Bit 500µs pulse, 3500µs pause
Stop Bit 500µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order MSB first

PANASONIC

PANASONIC Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 56 data bits + 1 stop bit
Data 24 bits (010000000000010000000001) + 16 address bits + 16 command bits
Start Bit 3600µs pulse, 1600µs pause
0 Bit 565µs pulse, 316µs pause
1 Bit 565µs pulse, 1140µs pause
Stop Bit 565µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order LSB first?

PENTAX

PENTAX Value
Frequency 38 kHz
Coding pulse distance
Frame 1 start bit + 6 data bits + 1 stop bit
Data 6 command bits
Start Bit 2200µs pulse, 27100µs pause
0 Bit 1000µs pulse, 1000µs pause
1 Bit 1000µs pulse, 3000µs pause
Stop Bit 1000µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order MSB first

KATHREIN

KATHREIN Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 11 data bits + 1 stop bit
Data 4 address bits + 7 command bits
Start Bit 210µs pulse, 6218µs pause
0 Bit 210µs pulse, 1400µs pause
1 Bit 210µs pulse, 3000µs pause
Stop Bit 210µs pulse
Repetition none
Keyboard Repetition after 35ms?
Bit Order MSB first

LEGO

LEGO Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 16 data bits + 1 stop bit
Data 12 command bits + 4 crc bits
Start Bit 158µs pulse, 1026µs pause
0 Bit 158µs pulse, 263µs pause
1 Bit 158µs pulse, 553µs pause
Stop Bit 158µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order MSB first

VINCENT

VINCENT Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 32 data bits + 1 stop bit
Data 16 address bits + 8 command bits + 8 repeated command bits
Start Bit 2500µs pulse, 4600µs pause
0 Bit 550µs pulse, 550µs pause
1 Bit 550µs pulse, 1540µs pause
Stop Bit 550µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order MSB first?

THOMSON

THOMSON Value
Frequency 33 kHz
Coding pulse distance
Frame 0 Start Bits + 12 data bits + 1 stop bit
Data 4 address bits + 1 toggle bit + 7 command bits
0 Bit 550µs pulse, 2000µs pause
1 Bit 550µs pulse, 4500µs pause
Stop Bit 550µs pulse
Repetition none
Keyboard Repetition after 35ms
Bit Order MSB first?

TELEFUNKEN

TELEFUNKEN Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 15 data bits + 1 stop bit
Data 0 address bits + 15 command bits
Start Bit 600µs pulse, 1500µs pause
0 Bit 600µs pulse, 600µs pause
1 Bit 600µs pulse, 1500µs pause
Stop Bit 600µs pulse
Repetition none
Keyboard Repetition unknown
Bit Order MSB first?

RCCAR

RCCAR Value
Frequency 38 kHz?
Coding pulse distance
Frame 1 start bit + 13 data bits + 1 stop bit
Data 13 command bits
Start Bit 2000µs pulse, 2000µs pause
0 Bit 600µs pulse, 900µs pause
1 Bit 600µs pulse, 450µs pause
Stop Bit 600µs pulse
Repetition none
Keyboard Repetition after 40ms?
Bit Order LSB first


RCMM

RCMM Value
Frequency 36 kHz
Coding pulse distance
Frame RCMM32 1 start bit + 32 data bits + 1 stop bit
Frame RCMM24 1 start bit + 24 data bits + 1 stop bit
Frame RCMM12 1 start bit + 12 data bits + 1 stop bit
Data RCMM32 16 address bits (= 4 mode bits + 12 device bits) + 1 toggle bit + 15 command bits
Data RCMM24 16 address bits (= 4 mode bits + 12 device bits) + 1 toggle bit + 7 command bits
Data RCMM12 4 address bits (= 2 mode bits + 2 device bits) + 8 command bits
Start Bit 500µs pulse, 220µs pause
00 Bits 230µs pulse, 220µs pause
01 Bits 230µs pulse, 380µs pause
10 Bits 230µs pulse, 550µs pause
11 Bits 230µs pulse, 720µs pause
Stop Bit 230µs pulse
Repetition none
Keyboard Repetition after 80ms
Bit Order LSB first
Pulse Width Coding

Pulse Width Protocols

 

SIRCS

SIRCS Value
Frequency 40 kHz
Coding pulse Width
Frame 1 start bit + 12-20 data bits, no stop bit
Data 7 command bits + 5 address bits + bis zu 8 zusätzliche Bits
Start Bit 2400µs pulse, 600µs pause
0 Bit 600µs pulse, 600µs pause
1 Bit 1200µs pulse, 600µs pause
Repetition twice after approx. 25ms, that means: 2nd und 3rd Frame
Keyboard Repetition starting with 4th identical frame, distance approx. 25ms
Bit Order LSB first
Pulse Distance Width Coding

Pulse distance Width Protocols

 

NUBERT

NUBERT Value
Frequency 36 kHz?
Coding pulse distance Width
Frame 1 start bit + 10 data bits + 1 stop bit
Data 0 address bits + 10 command bits ?
Start Bit 1340µs pulse, 340µs pause
0 Bit 500µs pulse, 1300µs pause
1 Bit 1340µs pulse, 340µs pause
Stop Bit 500µs pulse
Repetition once after 35ms
Keyboard Repetition 3rd, 5th, 7th etc. indentical frame
Bit Order MSB first?

FAN

This protocol is very similar to NUBERT, but here it will be sent only one frame. Additionally there are 11 instead of 10 data bits and no stop bit. The pause time between frame repetitions is substantial lower.

FAN Value
Frequency 36 kHz
Coding pulse distance Width
Frame 1 start bit + 11 data bits + 0 stop bits
Data 0 address bits + 11 command bits
Start Bit 1280µs pulse, 380µs pause
0 Bit 380µs pulse, 1280µs pause
1 Bit 1280µs pulse, 380µs pause
Stop Bit 500µs pulse
Repetition none
Keyboard Repetition after 6,6ms pause
Bit Order MSB first

SPEAKER

SPEAKER Value
Frequency 38 kHz?
Coding pulse distance Width
Frame 1 start bit + 10 data bits + 1 stop bit
Data 0 address bits + 10 command bits ?
Start Bit 440µs pulse, 1250µs pause
0 Bit 440µs pulse, 1250µs pause
1 Bit 1250µs pulse, 440µs pause
Stop Bit 440µs pulse
Repetition once after approx. 38ms
Keyboard Repetition 3rd, 5th, 7th ... identical frame
Bit Order MSB first?

ROOMBA

ROOMBA Value
Frequency 38 kHz?
Coding pulse distance Width
Frame 1 start bit + 7 data bits + 0 Stop Bit
Data 0 address bits + 7 command bits
Start Bit 2790µs pulse, 930µs pause
0 Bit 930µs pulse, 2790µs pause
1 Bit 2790µs pulse, 930µs pause
Stop Bit no stop bit
Repetition 3 times after 18ms?
Keyboard Repetition unknown
Bit Order MSB first
Biphase Coding

Biphase Protocols

 

RC5 + RC5X

RC5 + RC5X Value
Frequency 36 kHz
Coding Biphase (Manchester)
Frame RC5 2 Start Bits + 12 data bits + 0 stop bits
Data RC5 1 toggle bit + 5 address bits + 6 command bits
Frame RC5X 1 start bit + 13 data bits + 0 Stop Bit
Data RC5X 1 inverteds command bit + 1 toggle bit + 5 address bits + 6 command bits
Start Bit 889µs pause, 889µs pulse
0 Bit 889µs pulse, 889µs pause
1 Bit 889µs pause, 889µs pulse
Stop Bit no stop bit
Repetition none
Keyboard Repetition after approx. 100ms
Bit Order MSB first

S100

Ähnlich zu RC5x, aber 14 statt 13 data bits und 56kHz Modulation

S100 Value
Frequency 56 kHz
Coding Biphase (Manchester)
Frame 1 start bit + 14 data bits + 0 Stop Bit
Data 1 inverteds command bit + 1 toggle bit + 5 address bits + 7 command bits
Start Bit 889µs pause, 889µs pulse
0 Bit 889µs pulse, 889µs pause
1 Bit 889µs pause, 889µs pulse
Stop Bit no stop bit
Repetition none
Keyboard Repetition after approx. 100ms
Bit Order MSB first

RC6 + RC6A

RC6 + RC6A Value
Frequency 36 kHz
Coding Biphase (Manchester)
Frame RC6 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 16 data bits + 2666µs pause
Frame RC6A 1 start bit + 1 Bit "1" + 3 mode bits (110) + 1 toggle bit + 31 data bits + 2666µs pause
Data RC6 8 address bits + 8 Command Bits
Data RC6A "1" + 14 customer bits + 8 system bits + 8 command bits
Data RC6A Pace (Sky) "1" + 3 mode bits ("110") + 1 toggle bit(UNUSED "0") + 16 Bit + 1 toggle(!) + 15 command bits
Start Bit 2666µs pulse, 889µs pause
Toggle 0 Bit 889µs pause, 889µs pulse
Toggle 1 Bit 889µs pulse, 889µs pause
0 Bit 444µs pause, 444µs pulse
1 Bit 444µs pulse, 444µs pause
Stop Bit no stop bit
Repetition none
Keyboard Repetition after approx. 100ms
Bit Order MSB first

GRUNDIG + NOKIA

GRUNDIG + NOKIA Value
Frequency 38 kHz (?)
Coding Biphase (Manchester)
Frame-Paket 1 Start-Frame + 19,968ms pause + N Info-Frames + 117,76ms pause + 1 Stop-Frame
Start-Frame 1 pre bit + 1 start bit + 9 data bits (all 1) + 0 stop bits
Info-Frame 1 pre bit + 1 start bit + 9 data bits + 0 stop bits
Stop-Frame 1 pre bit + 1 start bit + 9 data bits (all 1) + 0 stop bits
Data Grundig 9 command bits + 0 address bits
Data Nokia 8 command bits + 8 address bits
Pre Bit 528µs pulse, 2639µs pause
Start Bit 528µs pulse, 528µs pause
0 Bit 528µs pause, 528µs pulse
1 Bit 528µs pulse, 528µs pause
Stop Bit no stop bit
Repetition none
Keyboard Repetition after approx. 117,76ms
Bit Order LSB first

IR60 (SDA2008)

IR60 Value
Frequency 30 kHz
Coding Biphase (Manchester)
Start Frame 1 start bit + 101111 + 0 stop bits + 22ms pause
Data Frame 1 start bit + 7 data bits + 0 stop bits
Data 0 address bits + 7 command bits
Start Bit 528µs pulse, 2639µs pause
0 Bit 528µs pause, 528µs pulse
1 Bit 528µs pulse, 528µs pause
Stop Bit no stop bit
Repetition none
Keyboard Repetition after approx. 117,76ms
Bit Order LSB first

SIEMENS + RUWIDO

SIEMENS + RUWIDO Value
Frequency 36 kHz? (Merlin-Tastatur mit Ruwido protocol: 56 kHz)
Coding Biphase (Manchester)
Frame Siemens 1 start bit + 22 data bits + 0 stop bits
Frame Ruwido 1 start bit + 17 data bits + 0 stop bits
Data Siemens 11 address bits + 10 command bits + 1 inverteds Bit (letztes Bit davor nochmal invertiert)
Data Ruwido 9 address bits + 7 command bits + 1 inverteds Bit (letztes Bit davor nochmal invertiert)
Start Bit 275µs pulse, 275µs pause
0 Bit 275µs pause, 275µs pulse
1 Bit 275µs pulse, 275µs pause
Stop Bit no stop bit
Repetition once with repeat bit set (?)
Keyboard Repetition after approx. 100ms (?)
Bit Order MSB first

A1TVBOX

A1TVBOX Value
Frequency 38 kHz?
Coding Biphase (Manchester) asymmetrisch
Frame 2 Start Bits + 16 data bits + 0 stop bits
Data 8 address bits + 8 command bits
Start Bits "10", also 250µs pulse, 150µs + 150µs pause, 250µs pulse
0 Bit 150µs pause, 250µs pulse
1 Bit 250µs pulse, 150µs pause
Stop Bit no stop bit
Repetition none
Keyboard Repetition unknown
Bit Order MSB first

MERLIN

MERLIN Value
Frequency 56 kHz
Coding Biphase (Manchester) asymmetric
Frame 2 Start Bits + 18 data bits + 0 stop bits
Data 8 address bits + 10 command bits
Start Bits "10", also 210µs pulse, 210µs + 210µs pause, 210µs pulse
0 Bit 210µs pause, 210µs pulse
1 Bit 210µs pulse, 210µs pause
Stop Bit no stop bit
Repetition none
Keyboard Repetition unknown
Bit Order MSB first

ORTEK

ORTEK Value
Frequency 38 kHz?
Coding Biphase (Manchester) symmetrisch
Frame 2 Start Bits + 18 data bits + 0 stop bits
Data 6 address bits + 2 special bits + 6 command bits + 4 special bits
Start Bit 2000µs pulse, 1000µs pause
0 Bit 500µs pause, 500µs pulse
1 Bit 500µs pulse, 500µs pause
Stop Bit no stop bit
Repetition 2 additinal frames with special bits set
Keyboard Repetition only repetition of the 2nd frame
Bit Order MSB first

Pulse Position Protocols

NETBOX

NETBOX Value
Frequency 38 kHz?
Coding pulse Position
Frame 1 start bit + 16 data bits, no stop bit
Data 3 address bits + 13 command bits
Start Bit 2400µs pulse, 800µs pause
Bit Length 800µs
Repetition none
Keyboard Repetition after approx. 35ms?
Bit Order LSB first

Software History

Changes of IRMP in 3.0.x

Version 3.0.8:

  • 2017-08-25: New protocol: IRMP16 for transparent 16 bit data communication

Version 3.0.4:

  • 2016-11-18: Corrected buffer overflow in irmp-main-avr-uart.c

Version 3.0.3:

Version 3.0.2:

Version 3.0.0:

  • 2016-01-16: Some corrections of port to ESP8266
  • 2016-01-16: Added port to MBED
  • 2016-01-16: Added several hardware dependent example main source files

Older Versions

  • 2015-11-17: New protocol: PANASONIC (Beamer)
  • 2015-11-17: Port to ESP8266
  • 2015-11-17: Port to Teensy (3.x)
  • 2015-11-10: Added support for STM8 microcontroller
  • 2015-09-20: New protocol: TECHNICS
  • 2015-06-15: New protocol: ACP24
  • 2015-05-29: New protocol: S100
  • 2015-05-29: Some smaller corrections
  • 2015-05-28: Added Logging for XMega
  • 2015-05-28: Timing corrections for FAN protocol
  • 2015-05-27: New protocol: MERLIN
  • 2015-05-27: New protocol: FAN
  • 2015-05-18: Added F_CPU macro for STM32L1XX
  • 2015-05-18: Some corrections for XMega port
  • 2015-04-23: New protocol: PENTAX
  • 2015-04-23: Port to AVR XMega
  • 2014-09-19: Bugfix: added missing newline before #else
  • 2014-09-18: Added logging for ARM STM32F10X
  • 2014-09-17: Corrected PROGMEM access to array irmp_protocol_names[].
  • 2014-09-15: Changed timing tolerances for KASEIKYO protocol
  • 2014-09-15: Moved irmp_protocol_names to flash, additional UART routines in irmp-main-avr-uart.c
  • 2014-07-21: Port to PIC 12F1840
  • 2014-07-09: New protocol: SAMSUNG48
  • 2014-07-09: Some small corrections
  • 2014-07-01: Added logging for ARM_STM32F4XX
  • 2014-07-01: IRMP port for PIC XC8 compiler, removed variadic macros because of stupid XC8 compiler :-(
  • 2014-06-05: New protocol: LGAIR
  • 2014-05-30: New protocol: SPEAKER
  • 2014-05-30: Optimized timings for SAMSUNG protocol
  • 2014-02-20: Corrected decoding of SIEMENS protocol
  • 2014-02-19: New protocols: RCMM32, RCMM24 and RCMM12
  • 2014-09-17: Optimized timing for ROOMBA
  • 2013-04-09: New protocol: ROOMBA
  • 2013-04-09: Optimized detection of ORTEK (Hama) frames
  • 2013-03-19: New protocol: ORTEK (Hama)
  • 2013-03-19: New protocol: TELEFUNKEN
  • 2013-03-12: Changed timing tolerancies for RECS80- and RECS80EXT protocol
  • 2013-01-21: Corrected detection of repetition frame beim DENON protocol
  • 2013-01-17: Corrected frame detection beim DENON protocol
  • 2012-12-11: New protocol: A1TVBOX
  • 2012-12-07: Improved detection von DENON repetition frame
  • 2012-11-19: Port to Stellaris LM4F120 TI Launchpad (ARM Cortex M4)
  • 2012-11-06: Corrected DENON frame detection
  • 2012-10-26: Some timer corrections and adaptations for Arduino
  • 2012-07-11: New protocol: BOSE
  • 2012-06-18: Added support for ATtiny87/167
  • 2012-06-05: Some smaller corrections of port to ARM STM32
  • 2012-06-05: Correction of include in irmpextlog.c
  • 2012-06-05: Bugfix, if only NEC and NEC42 activated
  • 2012-05-23: Port to ARM STM32
  • 2012-05-23: Bugfix frame detection for DENON protocol
  • 2012-02-27: Bugfix in IR60-Decoder
  • 2012-02-27: Bugfix in CRC calculation of KASEIKYO frames
  • 2012-02-27: Port to C18 Compiler for PIC microcontrollers
  • 2012-02-13: Bugfix: most significant bit in Address wrong in NEC protocol, if NEC42 protocol activated, too
  • 2012-02-13: Corrected timing of SAMSUNG- and SAMSUNG32 protocol
  • 2012-02-13: KASEIKYO: Genre2 bits will be now stored in upper nibble of flags
  • 2011-09-20: New protocol: KATHREIN
  • 2011-09-20: New protocol: RUWIDO
  • 2011-09-20: New protocol: THOMSON
  • 2011-09-20: New protocol: IR60 (SDA2008)
  • 2011-09-20: New protocol: LEGO
  • 2011-09-20: New protocol: NEC16
  • 2011-09-20: New protocol: NEC42
  • 2011-09-20: New protocol: NETBOX
  • 2011-09-20: Port to ATtiny84 and ATtiny85
  • 2011-09-20: Improved key repetition detection in RC5 protocol
  • 2011-09-20: Improved decoding of Biphase protocols
  • 2011-09-20: Fixed some smaller bugs in RECS80 decoder
  • 2011-09-20: Corrected detection of additional bits in SIRCS protocol
  • 2011-01-18: Some corrections for SIEMENS protocol
  • 2011-01-18: New protocol: NIKON
  • 2011-01-18: SIRCS: additional bits (>12) will be stored in address
  • 2011-01-18: Some timing corrections for DENON protocol
  • 2010-09-04: Bugfix for F_INTERRUPTS >= 16000
  • 2010-09-02: New protocol: RC6A
  • 2010-08-29: New protocol: JVC
  • 2010-08-29: KASEIKYO protocol: genre bits will be now stored
  • 2010-08-29: KASEIKYO protocol: Improved handling of repetition frames
  • 2010-08-29: Improved support of APPLE protocols.
  • 2010-07-01: Bugfix: added a timeout for NEC repetition frames. This avoids 'ghost commands'.
  • 2010-06-25: New protocol: RCCAR
  • 2010-06-25: Extended keyboard detection for FDC protocol (IR keyboard)
  • 2010-06-25: Interrupt frequency now up to 20kHz possible
  • 2010-06-09: New protocol: FDC (IR-keyboard)
  • 2010-06-09: Corrected timing for DENON protocol
  • 2010-06-02: New protocol: SIEMENS (Gigaset)
  • 2010-05-26: New protocol: NOKIA
  • 2010-05-26: Bugfix: detection of long keyboard press for GRUNDIG protocol
  • 2010-05-17: Bugfix SAMSUNG32 protocol: corrected command bit mask
  • 2010-05-16: New protocol: GRUNDIG
  • 2010-05-16: Improved handling of automatic frame repetitions for SIRCS-, SAMSUNG32-, and NUBERT protocol
  • 2010-04-28: Only some cosmetic code optimizations
  • 2010-04-16: Improved all timing tolerancies
  • 2010-03-29: Bugfix: detection of multiple NEC repetition frames
  • 2010-03-29: Moved configuration data to irmpconfig.h
  • 2010-03-29: Introduced a program version in README.txt: Version 1.0
  • 2010-03-17: New protocol: NUBERT
  • 2010-03-16: Correction of RECS80 start bit timings
  • 2010-03-16: New protocol: RECS80 Extended
  • 2010-03-15: Some optimizations
  • 2010-03-14: Port to PIC
  • 2010-03-11: Some adjustements for some ATMegas
  • 2010-03-07: Bugfix: Reset of state machine after a incomplete RC5 frame
  • 2010-03-05: New protocol: APPLE
  • 2010-03-05: Data irmp_data.addr + irmp_data.command will be now stored in the bit order of the appropriate protocol
  • 2010-03-02: SIRCS: corrected detection and suppression of automatic frame repetitions
  • 2010-03-02: SIRCS: device ID bits will be now stored in irmp_data.command (not irmp_data.address anymore)
  • 2010-03-02: Enlargement of scan buffers (for logging)
  • 2010-02-24: New variable flags in IRMP_DATA for detection of long key press
  • 2010-02-20: Bugfix DENON protocol: repetition frame is now basically inverted
  • 2010-02-19: Detection of NEC protocol-Varianten, z. B. APPLE-Fernbedienung
  • 2010-02-19: Detection of RC6- and DENON protocol
  • 2010-02-19: Some improvements for RC5 decoders (Bugfixes)
  • 2010-02-13: Bugfix: Puls/Pause counters were 1 too low, now better detection of protokols with very short pulses
  • 2010-02-13: Improved detection of NEC repetition frames
  • 2010-02-12: New: RC5 protocol
  • 2010-01-07: First version

Literature

IR Abstract

SIRCS Protocol

NEC Protocol

ACP24 Protocol

The ACP24-Protocol is used by Stiebel-Eltron-Aircons

The structure of the 70 databits is :

             1         2         3         4         5         6
   0123456789012345678901234567890123456789012345678901234567890123456789
   N VVMMM    ? ???    t vmA x                 y                     TTTT
   0011001000000111000010001010000000000000000010000000000000000000001111on, temp=30

These are converted into the following 16 bits from irmp_data.command:

       5432109876543210
       NAVVvMMMmtxyTTTT

Meaning of the symbols:

   TTTT = Temperature + 15 degree
           TTTT
           ----------
           0000        ???
           0001        ???
           0010        ???
           0011        18 degree
           0100        19 degree
           0101        20 degree
           0110        21 degree
           ...
           1111        30 degree
   N    = Nightmode
           N
           ----------
           0           off
           1           on
   VV   = fan, v must be 1!
           VV   v
           ----------
           00   1      level 1
           01   1      level 2
           10   1      level 3
           11   1      Automatic
   MMM  = Mode
           MMM  m
           ----------
           000  0      turn off
           001  0      turn on
           001  1      cooling
           010  1      fan
           011  1      demist
           100  1      ???
           101  1      ---
           110  1      ---
           111  1      ---
   A    = Automatic-Programm
           A
           ----------
           0           off
           1           on
   t   = Timer
           t   x y
           ----------
           1   1 0     Timer 1
           1   0 1     Timer 2

To control the air con via IRSND, the following functions can be used:

#include "irmp.h"
#include "irsnd.h"

#define IRMP_ACP24_TEMPERATURE_MASK         0x000F                                          // TTTT

#define IRMP_ACP24_SET_TIMER_MASK           (1<<6)                                          // t
#define IRMP_ACP24_TIMER1_MASK              (1<<5)                                          // x
#define IRMP_ACP24_TIMER2_MASK              (1<<4)                                          // y

#define IRMP_ACP24_SET_MODE_MASK            (1<<7)                                          // m
#define IRMP_ACP24_MODE_POWER_ON_MASK       (1<<8)                                          // MMMm = 0010 Einschalten
#define IRMP_ACP24_MODE_COOLING_MASK        (IRMP_ACP24_SET_MODE_MASK | (1<<8))             // MMMm = 0011 Kuehlen
#define IRMP_ACP24_MODE_VENTING_MASK        (IRMP_ACP24_SET_MODE_MASK | (1<<9))             // MMMm = 0101 Lueften
#define IRMP_ACP24_MODE_DEMISTING_MASK      (IRMP_ACP24_SET_MODE_MASK | (1<<10) | (1<<8))   // MMMm = 1001 Entfeuchten

#define IRMP_ACP24_SET_FAN_STEP_MASK        (1<<11)                                         // v
#define IRMP_ACP24_FAN_STEP_MASK            0x3000                                          // VV
#define IRMP24_ACP_FAN_STEP_BIT             12                                              // VV
#define IRMP_ACP24_AUTOMATIC_MASK           (1<<14)                                         // A
#define IRMP_ACP24_NIGHT_MASK               (1<<15)                                         // N


// possible values for acp24_set_mode();
#define ACP24_MODE_COOLING                  1
#define ACP24_MODE_VENTING                  2
#define ACP24_MODE_DEMISTING                3

static uint8_t temperature = 18;                                                    // 18 degrees

static void
acp24_send (uint16_t cmd)
{
    IRMP_DATA irmp_data;

    cmd |=  (temperature - 15) & IRMP_ACP24_TEMPERATURE_MASK;

    irmp_data.protocol = IRMP_ACP24_PROTOCOL;
    irmp_data.address  = 0x0000;
    irmp_data.command  = cmd;
    irmp_data.flags    = 0;

    irsnd_send_data (&irmp_data, 1);
}

void
acp24_set_temperature (uint8_t temp)
{
    uint16_t    cmd = IRMP_ACP24_MODE_POWER_ON_MASK;

    temperature = temp;
    acp24_send (cmd);
}

void
acp24_off (void)
{
    uint16_t    cmd = 0;
    acp24_send (cmd);
}

#define ACP_FAN_STEP1       0
#define ACP_FAN_STEP2       1
#define ACP_FAN_STEP3       2
#define ACP_FAN_AUTOMATIC   3

void
acp24_fan (uint8_t fan_step)
{
    uint16_t    cmd = IRMP_ACP24_MODE_POWER_ON_MASK;

    cmd |= IRMP_ACP24_SET_FAN_STEP_MASK | ((fan_step << IRMP24_ACP_FAN_STEP_BIT) & IRMP_ACP24_FAN_STEP_MASK);

    acp24_send (cmd);
}

void
acp24_set_mode (uint8_t mode)
{
    uint16_t    cmd = 0;

    switch (mode)
    {
        case ACP24_MODE_COOLING:    cmd = IRMP_ACP24_MODE_COOLING_MASK;     break;
        case ACP24_MODE_VENTING:    cmd = IRMP_ACP24_MODE_VENTING_MASK;     break;
        case ACP24_MODE_DEMISTING:  cmd = IRMP_ACP24_MODE_DEMISTING_MASK;   break;
        default: return;
    }
    acp24_send (cmd);
}

void
acp24_program_automatic (void)
{
    uint16_t    cmd = IRMP_ACP24_MODE_POWER_ON_MASK | IRMP_ACP24_AUTOMATIC_MASK;
    acp24_send (cmd);
}

void
acp24_program_night (void)
{
    uint16_t    cmd = IRMP_ACP24_MODE_POWER_ON_MASK | IRMP_ACP24_NIGHT_MASK;
    acp24_send (cmd);
}

LGAIR Protocol

The LG Air Con is controlled by an 'intelligent' remote. These are the encoded data:

   Command                 AAAAAAAA  PW  Z  S  T  mmm  tttt  vvvv  PPPP
   --------------------------------------------------------------------
   ON 23C                  10001000  00  0  0  0  000  1000  0100  1100
   ON 26C                  10001000  00  0  0  0  000  1011  0100  1111
   OFF                     10001000  11  0  0  0  000  0000  0101  0001
   TURN OFF                10001000  11  0  0  0  000  0000  0101  0001  (18C currently, identical with off)
   TEMP DOWN 23C           10001000  00  0  0  1  000  1000  0100  0100
   MODE (to mode0, 23C)    10001000  00  0  0  1  000  1000  0100  0100
   TEMP UP (24C)           10001000  00  0  0  1  000  1001  0100  0101
   TEMP DOWN 24C           10001000  00  0  0  1  000  1001  0100  0101
   TEMP UP (25C)           10001000  00  0  0  1  000  1010  0100  0110
   TEMP DOWN 25C           10001000  00  0  0  1  000  1010  0100  0110
   TEMP UP (26C)           10001000  00  0  0  1  000  1011  0100  0111
   MODE                    10001000  00  0  0  1  011  0111  0100  0110  (to mode1, 22C - when switching to mode1 temp automaticall sets to 22C)
   ON (mode1, 22C)         10001000  00  0  0  0  011  0111  0100  1110
   MODE                    10001000  00  0  0  1  001  1000  0100  0101  (to mode2, no temperature displayed)
   ON (mode2)              10001000  00  0  0  0  001  1000  0100  1101
   MODE (to mode3, 23C)    10001000  00  0  0  1  100  1000  0100  1000
   ON (mode3, 23C)         10001000  00  0  0  0  100  1000  0100  0000
   VENTILATION SLOW        10001000  00  0  0  1  000  0011  0000  1011
   VENTILATION MEDIUM      10001000  00  0  0  1  000  0011  0010  1101
   VENTILATION HIGH        10001000  00  0  0  1  000  0011  0100  1111
   VENTILATION LIGHT       10001000  00  0  0  1  000  0011  0101  0000
   SWING ON/OFF            10001000  00  0  1  0  000  0000  0000  0001


   Format:     1 start bit + 8 address bits + 16 data bits + 4 checksum bits + 1 stop bit
   Address:    AAAAAAAA = 0x88 (8 bits)
   Data:       PW Z S T MMM tttt vvvv PPPP (16 bits)
               PW:         Power:     00 = On, 11 = Off
               Z:          N/A:       Always 0
               S:          Swing:     1 = Toggle swing, all other data bits are zeros.
               T:          Temp/Vent: 1 = Set temperature and ventilation
               MMM:        Mode, can be combined with temperature
                           000=Mode 0
                           001=Mode 2
                           010=????
                           011=Mode 1
                           100=Mode 3
                           101=???
                           111=???
               tttt:       Temperature:
                           0000=used by OFF command
                           0001=????
                           0010=????
                           0011=18°C
                           0100=19°C
                           0101=20°C
                           0110=21°C
                           0111=22°C
                           1000=23°C
                           1001=24°C
                           1010=25°C
                           1011=26°C
                           1011=27°C
                           1100=28°C
                           1101=29°C
                           1111=30°C
               vvvv:       Ventilation:
                           0000=slow
                           0010=medium
                           0011=????
                           0100=high
                           0101=light
                           0110=????
                           0111=????
                           ...
                           1111=????
   Checksum:   PPPP = (DataNibble1 + DataNibble2 + DataNibble3 + DataNibble4) & 0x0F

NEC16 Protocol (JVC)

SAMSUNG Protocol

(was reverse engineered by several protocols (Daewoo or similar), so no direkt link to SAMSUNG documents is available)

Here is a link to the Daewoo-protocol, which uses the same principle of the sync-bits in the center of a frame, but words with different timings:

MATSUHITA Protocol

KASEIKYO Protocol ("Japan Protocol")

RECS80 and RECS80 Extended Protocol

RC5 and RC5x Protocol

Denon Protocol

RC6 and RC6A Protocol

Bang & Olufsen

Grundig Protocol

Nokia Protocol

IR60 (SDA2008 and MC14497P)

LEGO Power Functions RC

RCMM Protocol

Other Protocols

IRMP on Youtube

Other Artikels

Whitepaper von Martin Gotschlich, Infineon Technologies AG

Hardware / IRMP Projects

Remote IRMP

Infrared sender und receiver controlled via ip network with Android smartphone as remote control:

* http://www.mikrocontroller.net/articles/Remote_IRMP

IR Tester

IR tester with LCD by Klaus Leidinger:

IR Tester with AVR-NET-IO

IR tester for Pollin AVR-NET-IO with Pollin ADD-ON Board:

USB IR Remote Receiver

USB IR remote receiver by Hugo Portisch:

USB IR Receiver/Sender/Switch with Wakeup-Timer

USBASP

IR switch based on USBasp

Servo controlled IR Sender

Servo controlled IR Sender (adaptive) by Stefan Pendsa:

Adaptive IR Remote Control

Adaptive IR remote control by Robert and Frank M.

AVR Moodlight

AVR Moodlight by Axel Schwenke

STM8 Moodlight by Axel Schwenke

Infinity Mirror LED Ceiling Lamp

Infinity Mirror LED ceiling lamp with remote control by Philipp Meißner

Cinema Control

Cinema control by Owagner

Leading-Edge Control

leading-edge control:

IRDioder – Ikea Dioder Hack

Ikea Dioder Hack:

Expedit Coffee Bar

Ikea Expedit as coffee bar:

Arduino as IR Receiver

Arduino as IR Receiver:

IR Volume Control with Stellaris Launchpad

volume control with Stellaris Launchpad (ARM Cortex-M4F):

RemotePi Board

Shutdown RaspPI with IR remote control:

Ethernut & IRMP

IRMP under RTOS Ethernut:

LED strip Remote Control

LED strip remote control:

ADAT Audio Mixer

Audio Mixer:

Ethersex & IRMP

IRMP + IRSND Modul in Ethersex, a modular Firmware for AVR MCUs

Mastermind Solver

Mastermind solver with LED stripes and IR remote control:

A MythTV Remote Control without LIRC

PC Remote Control with ATtiny85

IRMP + IRSND Library for STM32F4

IRMP for STM32F4

IRSND for STM32F4

IRMP on STM32 - Construction Guidance

Seminar Paper - Extension of Arduino Plattform

  • www.eislab.fim.uni-passau.de/files/publications/2010/StudentDiener_ErweiterungDerArduinoPlattform.pdf

Acknowledgment

I thank Vlad Tepesch, Klaus Leidinger, Peter K., and Dániel Körmendi, who sent me many scan files of their IR remote controls.

I thank Christian F. for his tipps relating to the port to PIC MCUs, gera for the port to PIC-C18 compiler, kichi (Michael K.) for the port to ARM STM32, Markus Schuster for the port to TI's Stellaris LM4F120 Launchpad (ARM Cortex M4), Matthias Frank for the port to XMega, Wolfgang S. for the port to ESP8266, Achill Hasler for the port to Teensy, Axel Schwenke for the port to STM8.

Thanks to Dániel Körmendi, who added the LG-AIR protocol to IRSND. Thanks to Ulrich v.d. Kammer for the Pentax protocol extension in IRSND.

At least I will thank Jojo S. for his great job translating this documentation!

Discussion

You can discuss IRMP & IRSND in the german thread Infrared Multi Protocol Decoder.

Have fun with IRMP!