IRMP - english – Mikrocontroller.net (original) (raw)

By Frank M. (ukw)

This is the English translation of the German IRMP documentation.

Waveform of an NEC-format remote control signal

Project Intent:

Because RC5 is not only outdated, but obsolete, and because more and more electronic devices from Asian consumer electronics manufacturers are found in the home, 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 introduces 'IRMP' as "Infrared Multi Protocol Decoder" in detail. The counterpart, the IRSND IR encoder, can be found in this document.

IRMP - Infrared Multi Protocol Decoder

| | | | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Supported MCUs IRMP runs on numerous 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) STM32 with HAL library (NEW!) STM8 STM8S103F3 TI Stellaris LM4F120 Launchpad (ARM Cortex M4) ESP8266 (NEW!) ESP8266-EVB TEENSY 3.0 MK20DX256VLH7 (ARM Cortex-M4 72MHz) MBED (NEW!) LPC1347 Cortex-M3 72 MHz LPC4088 (Embedded Artists) ChibiOS HAL (NEW!) Various ARM Cortex MCUss, for example STM32, Kinetis, and NRF5 Officially supported MCU series More MCU series, community supported | Connection of a IR receiver module to MCU |

Supported IR Protocols

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

Supported Protocols

Protocol Vendor
A1TVBOX ADB (Advanced Digital Broadcast), e.g. 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 vendors which are members of the Japanese "Association for Electric Home Appliances" (AEHA).
KATHREIN KATHREIN
LEGO Lego
LGAIR LG air conditioners
MATSUSHITA Matsushita
MITSU_HEAVY Mitsubishi air conditioners
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, generic and many other Asian vendors.
NETBOX Netbox
Nikon Nikon
NUBERT Nubert, e.g. Subwoofer Systems
ORTEK Ortek, Hama
PANASONIC PANASONIC video projectors
PENTAX PENTAX
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
RCII T+A (NEW!)
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 conditioners
SAMSUNG Samsung
RUWIDO RUWIDO (e.g. T-Home Media Receiver, MERLIN keyboard(Pollin))
SIEMENS Siemens, e.g. Gigaset M740AV
SIRCS Sony
SPEAKER Speaker systems like X-Tensions
TECHNICS Technics
TELEFUNKEN Telefunken
THOMSON Thomson
VINCENT Vincent

New:

Starting with version 3.2, IRMP can also decode 433 MHz RF radio protocols.

Supported RF Protocols

Protocol Vendor
RF_GEN24 Generiv 24-bit format, e.g. Pollin 550666 radio-controlled receptacle
RF_X10 X10 PC RF remote control (Medion), Pollin 721815

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. Only the code selected by the user will be compiled .

History

The IRMP source for the AVR and PIC MCUs was 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

| | | | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Some vendors use their own proprietary protocols, such as Sony, Samsung, and Matsushita. Philips developed and used RC5.RC5 was seen in Europe as the standard IR protocol which was adopted by many European vendors. Nowadays RC5 is practically not used and can be considered "dead". Although the successor RC6 is used in current European hardware, it is also used rarely.Japanese vendors also tried to establish their own standard, the so called Kaseikyo (or "Japan") protocol. With a word length of 48 bits, it is more versatile. But it has not found wide use, though it is found in some appliances.Nowadays the NEC protocol is used (also mainly in Japanese devices) in both premium and generic products. I estimate the market share at 80% for the NEC protocol. Nearly all remotes in my daily use utilize the NEC IR code. This starts with the TV set, continues with the DVD player and the notebook remote all the way to the generic multimedia hard drive, just to mention a few examples. | NEC protocol, RGB remote control, T->A: 9.14ms, A->B: 4.42ms, B->C: 660us |

Coding methods

IRMP supports the following IR coding methods:

The pulses are modulated - usually at 36 kHz or 38 kHz - to reduce environmental influences such as indoor lighting or sunlight.

| | | | | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Pulse Distance Pulse distance coding can be identified by the following rule: there is only one pulse length and there are two different space lengths | Pulse distance coding |

| | | | | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | Pulse Width Pulse width coding can be identified by the following rule: there are two different pulse lengths and only one space length | Pulse width coding |

| | | | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Pulse Distance Width This is a mix of pulse distance and pulse width coding. Often the sum of pulse and space length is constant. The rule is: there are two different pulse lengths and two different space lengths. | Pulse distance width coding |

| | | | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | Biphase In biphase coding the order of pulse and space gives the bit value. Therefore a biphase boding can be identified by this criteria: there is exactly one pulse and space length, as well as the double pulse/space length Usually the length for the pulse and space are equal, meaning that the signal shape is symmetric. But IRMP also recognizes protocols which use different pulse and space lengths, for example the A1TVBOX protocol. | Biphase coding |

| | | | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Pulse Position Pulse position coding is known from commmon UARTs. Here, every bit has a fixed length. Depending on the value (0 or 1), it is a pulse or a space.Typical criteria for a pulse position protocol are: there are multiples of a basic pulse/space 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. | Pulse position coding |

Protocol Detection

Most of the protocols IRMP decodes have something in common: they exhibit a start bit whose timing is unique.

According to this start bit timing, most protocols can be identified. IRMP measures the timing of the start bit and adjusts its timing tables "on-the-fly" to the discovered protocol. Subsequent bits can then be read sequentially without the need to first store a complete frame. Thus, IRMP does not wait to read a complete frame but starts decoding directly after detecting the first pulse.

If the start bit is not unique, IRMP proceeds in parallel with multiple possible protocols. For example with two candidate protocols, once plausible reasons disqualify one protocol, the other protocol is used.

Detection is implemented as an interrupt-driven state machine which is called at a frequency of typically 15000 times per second. Among others, the state machine has the following states:

After that, the pulse and space lengths of the start bit are known. Now all enabled protocols are searched for these lengths. If a protocol matches, the timing table for this protocol is loaded. Subsequent bits are checked against the timing table to ensure they conform to it.

The state machine continues with the following states:

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 another sync bit within the frame (e.g. Samsung). These extra conditions are caught in the code by protocol-specific "special cases".

Switching to an other protocol can happen multiple times while receiving a frame, e.g. from NEC42 (42 bits) to NEC16 (8 bits + sync bit + 8 bits), if a premature sync bit is detected. Or from NEC/NEC42 (32/42 bits) to JVC (16 bits) if the stop bit occurs prematurely. It becomes difficult when, after detecting the start bit, two possible protocols use different coding methods, e.g. when the one protocol uses pulse distance coding and the other uses biphase coding (Manchester). In this case IRMP stores the necessary bits for both coding methods and later discards one or the other.

Furthermore, some remotes using particular protocols transmit repeat frames, either for redundancy (error detection) or for long key presses. Both kinds are detected by IRMP: error detection frames are detected by IRMP, but not passed to the application. Others are detected as long key presses and flagged by IRMP.

Download

Version 3.2.6, Date: 2021-01-27

Download stable version: Irmp.zip

Current development version of IRMP & IRSND:

Download Arduino library: GitHub or use Arduino "Tools / Manage Libraries..." and search for IRMP.

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

License

IRMP is Open Source Software and is released under the GPL v2, or (at your option) any later version.

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 in your application:

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 also runs on PIC processors. For the PIC-CCS compiler the necessary preprocessor defines are already set, such 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 protocol, 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 4.7.x of avr-gcc, the LTO option can be used to make the call of the external function irmp_ISR() from the main ISR more efficient. This improves the performance of the ISR a little.

Add the following compiler and linker options:

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

Configuration

IRMP is configured by parameters in irmpconfig.h:

Settings in irmpconfig.h

IRMP will decode all protocols listed above in one ISR. For this, some settings are needed. 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. A value of 15000 is usually a good compromise.

Default value:

#define F_INTERRUPTS 15000 // interrupts per second

On AVR controllers, the irmp-main-avr.c example uses Timer1 with 16 bits of resolution. If for any reasons Timer1 is not available, you can also use Timer2 with 8 bits of resolution.

In that case, configure Timer2 as follows:

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 change the ISR to Timer2 as well:

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

IRMP_SUPPORT_xxx_PROTOCOL

Here you can select which protocols to enable in IRMP. Common protocols are emabled by default.

To enable additional protocols or disable others to save memory, set the corresponding values in irmpconfig.h.

// 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 IR protocol enabled in IRMP consumes the amount of code noted above. 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. This usually requires a different IR receiver, so without that, you can disable these protocols. For example, you cannot receive the B&O protocol (455kHz) with a TSOP1738/TSOP31238.

Additionally, the SIEMENS/FDC/RCCAR can only be detected reliably at a frequency of 15 kHz or higher. For LEGO, 20 kHz is needed. To use these protocols, you must modify F_INTERRUPTS. Otherwise, during compilation you will get a warning and the corresponding protocols will automatically be disabled.

IRMP_PORT_LETTER + IRMP_BIT_NUMBER

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

Default value is PORT B6:

/*---------------------------------------------------------------------------

*/ #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:

/*----------------------------------------------------------------------------

*/ #elif defined (ARM_STM32) // use C13 as IR input on STM32

define IRMP_PORT_LETTER C

define IRMP_BIT_NUMBER 13

When using STM32 HAL library, define the constants IRSND_Transmit_GPIO_Port and IRSND_Transmit_Pin in STM32Cube (Main.h). In this case, it is not necessary to change the constants in irmpconfig.h:

/*---------------------------------------------------------------------------------------------------------------------------------------------------

*/ #elif defined (ARM_STM32_HAL) // IRSND_Transmit_GPIO_Port & IRSND_Transmit_Pin must be defined in STM32Cube

define IRSND_PORT_LETTER IRSND_Transmit_GPIO_Port//Port of Transmit PWM Pin e.g.

define IRSND_BIT_NUMBER IRSND_Transmit_Pin //Pim of Transmit PWM Pin e.g.

define IRSND_TIMER_HANDLER htim2 //Handler of Timer e.g. htim (see tim.h)

define IRSND_TIMER_CHANNEL_NUMBER TIM_CHANNEL_2 //Channel of the used Timer PWM Pin e.g. TIM_CHANNEL_2

define IRSND_TIMER_SPEED_APBX 64000000 //Speed of the corresponding APBx. (see STM32CubeMX: Clock Configuration)

And the corresponding section for STM8 MCUs:

/*----------------------------------------------------------------------------

*/ #elif defined (SDCC_STM8) // use PA1 as IR input on STM8

define IRMP_PORT_LETTER A

define IRMP_BIT_NUMBER 1

For PIC microcontrollers only the constant IRMP_PIN needs to be changed - depending on the compiler:

/*----------------------------------------------------------------------------

*/ #elif defined (PIC_C18) // use RB4 as IR input on PIC

define IRMP_PIN PORTBbits.RB4

/*----------------------------------------------------------------------------

*/ #elif defined (PIC_CCS) // use PB4 as IR input on PIC

define IRMP_PIN PIN_B4

When using ChibiOS HAL, define a pin with the name IR_IN in your board config (board.chcfg) of ChibiOS and regenerate the board files. To use another name for the pin, edit the constant IRMP_PIN in irmpconfig.h. Use the name of the pin from the board config and prefix it with "LINE_", as IRMP is using the "line" variant of the PAL interface:

/*---------------------------------------------------------------------------------------------------------------------------------------------------

*/ #elif defined(CHIBIOS_HAL)

define IRMP_PIN LINE_IR_IN // use pin names as defined in the board config file, prefixed with "LINE_"

IRMP_HIGH_ACTIVE

Default value:

define IRMP_HIGH_ACTIVE 0 // set to 1 if you use a RF receiver!

Most RF receivers use active-high signals, so when using an RF receiver instead of an IR sensor, set this value to 1.

NEU:

IRMP_ENABLE_RELEASE_DETECTION

Default value:

define IRMP_ENABLE_RELEASE_DETECTION 0 // enable detection of key releases

Set this value to 1 to enable detection of button release events. The function irmp_get_data() then sets the IRMP_FLAG_RELEASE bit in the struct member irmp_data.flags once code transmission ends. See the example in the section Debouncing.

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, any level change at the input causes the callback function to be called. This can be used 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

/*-----------------------------------------------------------------------------------------------------------------------

*/ void led_callback (uint_fast8_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_USE_IDLE_CALL

Normally the irmp_ISR() function is called continuously at the F_INTERRUPTS (10-20kHz) frequency. The microcontroller can rarely enter an energy-saving sleep mode, or must constantly wake up from it. If power consumption is important, e.g. on battery power, this approach is not optimal.

If IRMP_USE_IDLE_CALL' is enabled, IRMP detects if no IR transmission is ongoing and then calls the function irmp_idle(). This is microcontroller-specific and must be provided and linked by the user. The microcontroller can then be put to sleep while there is no ongoing transmission, thus reducing energy consumption.

It is recommended to deactivate the timer interrupt in irmp_idle() and to activate a pin change interrupt instead. Then the microcontroller can be put to sleep. When a falling edge is detected on the IR input pin, the pin change interrupt is disabled, the timer is reenabled and irmp_ISR() is called immediately. You can find an example for the use of irmp_idle() in irmp-main-chibios.c.

Using IRMP purely with pin change interrupts and without timer interrupts is not supported.

IRMP_USE_EVENT

When using IRMP with ChibiOS/RT or ChibiOS/NIL, you can use their Event module to wake a thread as soon as new IR data is received and decoded.

Set the IRMP_USE_EVENT constant in irmpconfig.h to 1 to enable this. IRMP_EVENT_BIT definies the value in the Event bitmask that should symbolize the IRMP event. Use IRMP_EVENT_THREAD_PTR to define the variable name of the thread pointer that the event is sent to.

Change irmpconfig.h like this:

/*------------------------------------------------------------------------------------------------------------------------------

*/ #if defined(CHIBIOS_RT) || defined(CHIBIOS_NIL)

ifndef IRMP_USE_EVENT

define IRMP_USE_EVENT 1 // 1: use event. 0: do not. default is 0

endif

if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_BIT)

define IRMP_EVENT_BIT 1 // event flag or bit to send

endif

if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_THREAD_PTR)

define IRMP_EVENT_THREAD_PTR ir_receive_thread_p // pointer to the thread to send the event to

extern thread_t *IRMP_EVENT_THREAD_PTR; // the pointer must be defined and initialized elsewhere

endif

#endif // CHIBIOS_RT || CHIBIOS_NIL

Now you can use the event in your ChibiOS project like this:

thread_t *ir_receive_thread_p = NULL;

static THD_FUNCTION(IRThread, arg) { ir_receive_thread_p = chThdGetSelfX(); [...] while (true) { // wait for event sent from irmp_ISR chEvtWaitAnyTimeout(ALL_EVENTS,TIME_INFINITE);

    if (irmp_get_data (&irmp_data))
        // use data in irmp_data

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 Unknown IR Protocols.

Using IRMP

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

IRMP separates these IR frames into 3 sections:

  1. protocol ID
  2. address or vendor code
  3. command

With the function

irmp_get_data (IRMP_DATA * irmp_data_p)

you can recall a decoded message. The return value is 1 if 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 that ultimately, you have three values (protocol, address and command) that can be evaluated with an if or switch statement. Here is a sample decoder which listens for keys 1-9 on a remote:

IRMP_DATA irmp_data;

if (irmp_get_data (&irmp_data)) { if (irmp_data.protocol == IRMP_NEC_PROTOCOL && // NEC protocol irmp_data.address == 0x1234) // Address 0x1234 { switch (irmp_data.command) { case 0x0001: key1_pressed(); break; // Key 1 case 0x0002: key2_pressed(); break; // Key 2 ... case 0x0009: key9_pressed(); break; // Key 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, generic, 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 Media Receiver #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 #define IRMP_PANASONIC_PROTOCOL 48 // Panasonic (video projector), start bits similar to KASEIKYO #define IRMP_MITSU_HEAVY_PROTOCOL 49 // Mitsubishi heavy air conditioner, similar timing to Panasonic video projector #define IRMP_VINCENT_PROTOCOL 50 // Vincent #define IRMP_SAMSUNGAH_PROTOCOL 51 // Samsung AH #define IRMP_IRMP16_PROTOCOL 52 // IRMP specific protocol for data transfer, e.g. between two microcontrollers via IR #define IRMP_GREE_PROTOCOL 53 // Gree climate #define IRMP_RCII_PROTOCOL 54 // RC II Infrared Remote Control Protocol for FM8 #define IRMP_METZ_PROTOCOL 55 // METZ #define IRMP_ONKYO_PROTOCOL 56 // Onkyo

The values of address and the command code of an unknown remote can be received and printed to UART or LCD. Then these values can be hard-coded in your decoder routine. Or you can write a learning routine, where you press keys to store the code into 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

To distinguish between a long key press or a single press, the IRMP_FLAG_REPETITION bit is provided. It is set in the struct member flags when a key on the remote is held, causing the same command to be repeated within a short period of time.

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 can be used to debounce the keys 0-9 by ignoring commands with the IRMP_FLAG_REPETITION bit set. For keys like 'VOLUME+' or 'VOLUME-' using the repetition can be useful, for example to fade a LED.

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

if (! (irmp_data.flags & IRMP_FLAG_REPETITION))
{
  // New key
  // ACTION!
}

NEW:

From version 3.2.2, key releases can be detected. In this case, the IRMP_FLAG_RELEASE flag is set once the remote control has ceased sending IR or RF frames.

Example:

IRMP_DATA irmp_data;

while (1)
{
    if (irmp_get_data (&irmp_data))
    {
        if (irmp_data.protocol == NEC_PROTOCOL && irmp_data.address == 0x1234)
        {
             if (irmp_data.command == 0x42 && irmp_data.flags == 0x00) // First frame, flags not set
             {
                 motor_on ();
             }
             else if (irmp_data.flags & IRMP_FLAG_RELEASE)             // Key is released
             {
                 motor_off ();
             }
        }
    }
}

In the above example, a motor is turned on when a specific button on the remote control is pressed. The motor will not stop again until you release the button.

Important when evaluating IRMP_FLAG_RELEASE:

You must not rely on irmp_data.command to still contain the original command code (0x42 here). There are remote controls (e.g. RF remotes for remote controlled receptacles) which send a special key release code when the key is released. Simply check that the irmp_data.address matches before evaluating the flag.

This feature must be enabled explicitly in irmpconfig.h by changing the configuration variable IRMP_ENABLE_RELEASE_DETECTION.

Principles of Operation

The "workhorse" of IRMP is the interrupt service routine irmp_ISR() which should be called 15000 times per second. When using a different rate, the constant F_INTERRUPTS in irmpconfig.h needs to be modified accordingly.

First, irmp_ISR() detects the length and the type of the start bit(s) and uses this to determine the protocol in use. As soon as the protocol is identified, subsequent bits are parametrized to read them efficiently until the IR transmission is complete.

To cut off critics:

I know that the ISR is quite large. But since it behaves like a state machine, the effective executed code per cycle is relatively small. As long as the input is "dark" (and that is the case most of the time ;-)) the spent time is vanishingly short. In the WordClock project for example, 8 ISRs are called with the same timer, of which irmp_ISR() just one of many. With a MCU clock of at least 8 MHz, no timing problems occured. Consequently, I see no problem with the length of the ISR.

A crystal is not mandatory, 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 Unknown IR Protocols

To enable logging in IRMP, modify the value of IRMP_LOGGING to 1 of irmpconfig.h on the line

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

When logging is enabled, the bright and dark phases are sent via UART at 9600 bits/s: 1=dark, 0=bright. The constants in the functions uart_init() and uart_putc() may need to be modified, depending on the AVR MCU used.

Note: for PIC microcontrollers there is a dedicated logging module named irmpextlog.c. This makes it possible to log via USB. This does not apply to the AVR version

By capturing these protocol scans with a terminal program and saving them to a text file, you can use these files to analyze the frames in order to add new protocols 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 is compatible with the IRMP model and modify the source code 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.

To compile IRMP, enter:

make -f makefile.lnx

This will generate 3 IRMP versions:

Starting IRMP

The calling syntax is:

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

Options are mutually exclusive, so only one option per call is valid:

Option:

-l List print a list with pulses and pauses -a analyze analyse the pulses/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 ...

Analysis

./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 (spaces) as horizontal bar graphs, whose distributions are not ideal bell curves due to the ASCII formatting. The narrower the measured peaks, the better the timing of the remote.

The above output can be read as:

Further there are two more spaces of different lengths (for bits 0 and 1). Reading these is left as an exercise to the 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 under Windows as well:

The same options apply as for the Linux version.

Long Output

As some output is very long, 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

VCR|-

Protocol Name Device Device Address
NEC Toshiba CT-9859 TV 0x5F40
Elta 8848 MP 4 DVD player 0x7F00
AS-218 Askey TV-View CHP03X (TV tuner card) 0x3B86
Cyberhome ??? Cyberhome DVD player 0x6D72
WD TV Live Western Digital Multimediaplayer 0x1F30
Canon WL-DC100 Kamera Canon PowerShot G5 0xB1CA
NEC16 Daewoo VCR 0x0015
KASEIKYO Technics EUR646497 SA-AX 730 AV receiver 0x2002
Panasonic TV TX-L32EW6 TV 0x2002
RC5 Loewe Assist/RC3/RC4 TV (remote control in TV mode) 0x0000
RC6 Philips TV TV (remote control in TV mode) 0x0000
SIRCS Sony RM-816 TV (remote control in TV mode) 0x0000
DENON DENON RC970 AVR3805 AV receiver 0x0008
DENON RC970 DVD/CD player 0x0002
DENON RC970 Tuner 0x0006
SAMSUNG32 Samsung AA59-00484A LE40D550 TV 0x0707
LG AKB72033901 BD370 Blu-Ray player 0x2D2D
APPLE Apple Apple iPod Dock 0x0020

Cameras

| | | | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | | IRMP supports more and more camera remotes like: PENTAX Nikon The array of commands is quite limited. Cameras understand only the shutter release command. | PENTAX protocol |

Here is a short table for PENTAX cameras:

Command Function
0x0000 Shutter release
0x0001 change zoom level

Because there is no address designated in the PENTAX protocol, for transmitting, it should be set to 0x0000 in IRSND.

For Nikon cameras, a crystal should be used because these cameras are quite sensitive to timing accuracy.

IR Keyboards

| | | | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | From version 1.7.0 on, IRMP also supports 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 | FDC-3402 keyboard |

The following values are returned as commands (irmp_data.command) :

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 on the left:

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

The ON/OFF key is an exception: This key only sends a code for a key press, not for the release.

If a key is held, this is indicated 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 locally on the MCU to decode the keycodes, or on the host system (e.g. PC) where the IRMP data structure is sent to. Therefore the function including preprocessor constants 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);

}

As a final example, use of the get_fdc_key() function:

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);
        }
    }
}

Non-printable characters are coded as follows:

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 get_fdc_key() function considers the state of the Shift, Ctrl, and Alt keys. As a result, not only capital letters can be entered, but also special characters with Alt + key combinations, e.g. Alt + m -> µ or Alt + q -> @. You can also 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 Protocols | Pulse Distance Coding |

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
Key repeat 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 key repeat
0 bit 560µs pulse, 560µs pause
1 bit 560µs pulse, 1690µs pause
Stop bit 560µs pulse
Repetition none
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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 to NEC)
0 bit 560µs pulse, 560µs pause (identical to NEC)
1 bit 560µs pulse, 1690µs pause (identical to NEC)
Stop bit 560µs pulse (identical to NEC)
Repetition none
Key repeat unknown
Bit order MSB first (differs from 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
Key repeat 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
Key repeat 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
Key repeat after approx. 45 msec
Bit order LSB first

MATSUSHITA

MATSUSHITA Value
Frequency 36 kHz
Coding pulse distance, timing identical to 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
Key repeat after 40ms pause
Bit order LSB first?

TECHNICS

TECHNICS Value
Frequency 36 kHz?
Coding pulse distance, timing identical to 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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 none
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)
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat 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
Key repeat after 80ms
Bit order LSB first

| | | | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | Pulse Width Protocols | Pulse Width Coding |

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 + up to 8 additional 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 and 3rd frame
Key repeat starting with 4th identical frame, distance approx. 25ms
Bit order LSB first

| | | | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Pulse distance Width Protocols | Pulse Distance Width Coding |

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
Key repeat 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
Key repeat 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
Key repeat 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 bits
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?
Key repeat unknown
Bit order MSB first

| | | | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | Biphase Protocols | Biphase Coding |

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 bits
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
Key repeat after approx. 100ms
Bit order MSB first

RCII

RCII Value
Frequency 31.25 kHz
Coding Biphase (Manchester)
Frame 1 pre bit + 1 start bit + 9 data bits + 0 stop bits
Data 0 address bits + 9 command bits
Pre Bit 512µs pulse, 2560µs pause
Start bit 1024µs pulse, no space
0 bit 512µs pause, 512µs pulse
1 bit 512µs pulse, 512µs pause
Stop bit no stop bit
Repetition none
Key repeat after approx. 118ms
Remarks An end command (111111111 = 0x1FF) is sent immediately after the button is released.
Bit-Order MSB first

S100

Similar to RC5x, but 14 instead of 13 data bits and 56kHz modulation

S100 Value
Frequency 56 kHz
Coding Biphase (Manchester)
Frame 1 start bit + 14 data bits + 0 stop bits
Data 1 inverted 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
Key repeat 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 bits + 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
Key repeat after approx. 100ms
Bit order MSB first

GRUNDIG + NOKIA

GRUNDIG + NOKIA Value
Frequency 38 kHz (?)
Coding Biphase (Manchester)
Frame packet 1 start frame + 19.968ms pause + N data frames + 117.76ms pause + 1 stop frame
Start frame 1 pre bit + 1 start bit + 9 data bits (all 1) + 0 stop bits
Data 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
Key repeat 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
Key repeat after approx. 117.76ms
Bit order LSB first

SIEMENS + RUWIDO

SIEMENS + RUWIDO Value
Frequency 36 kHz? (Merlin keyboard with 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 inverted bit (preceding bit inverted)
Data Ruwido 9 address bits + 7 command bits + 1 inverted bit (preceding bit inverted)
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 (?)
Key repeat after approx. 100ms (?)
Bit order MSB first

A1TVBOX

A1TVBOX Value
Frequency 38 kHz?
Coding Biphase (Manchester) asymmetric
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
Key repeat 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
Key repeat unknown
Bit order MSB first

ORTEK

ORTEK Value
Frequency 38 kHz?
Coding Biphase (Manchester) symmetric
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 additional frames with special bits set
Key repeat only repeats 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
Key repeat after approx. 35ms?
Bit order LSB first

Software History

Changes of IRMP in 3.2.x

Version 3.2.6:

Version 3.2.3:

Version 3.2.2:

Version 3.2.1:

Version 3.2.0:

Older Versions

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 to 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 direct 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:

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:

More example from the Arduino library:

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 Platform

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. and Antonio T. for their great job translating and revisioning this documentation!

Discussion

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

Have fun with IRMP!