IRMP - english
By Frank M. (ukw)
This is the English translation of the german IRMP documentation.
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.
IRMP - Infrared Multiprotocol Decoder
Supported MCUsIRMP has been implemented on several MCU families: AVR
XMega
PIC (CCS- and XC8/C18 compiler)
STM32
TI Stellaris
ESP8266 (NEW!)
TEENSY 3.0
MBED (NEW!)
ChibiOS HAL (NEW!)
|
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):
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 |
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 |
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 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
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:
- Pulse Distance, typ. Example: NEC
- Pulse Width, typ. Example: Sony SIRCS
- Biphase (Manchester), typ. Example: Philips RC5, RC6
- Pulse Position (NRZ), typ. Example: Netbox
- Pulse Distance Width, typ. Example: Nubert
The pulses are modulated - usually with 36 kHz or 38 kHz - to reduce environment influences such as Indoorlightning or sunlight.
Pulse DistanceA Pulse Distance Coding can be discovered by the following rule:
|
Pulse WidthA Pulse Width Coding can be discovered by the following rule:
|
Pulse Distance WidthThis is a mix from Pulse Distance and Pulse Width Coding. Often the sum of pulse and pause length is constant. The rule is:
|
BiphaseIn Biphase Coding the order of pulse and pause gives the bit value. Therefore a Biphase-Coding can be discovered by this criteria:
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 PositionThe 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:
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.2.6, Date: 2021-01-27
Download of stable version: Irmp.zip
Development version of IRMP & IRSND:
- SVN-Link: SVN
- SVN-Browser: IRMP in SVN
- Download Tarball Tarball.
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:
- irmp.c - IR-decoder core
- irmpprotocols.h - all protocoll definitions
- irmpsystem.h - target independant definitions for AVR/PIC/STM32
- irmp.h - Include file for the application
- irmpconfig.h - user configuration
Sample applications (main functions and timer configurations):
- irmp-main-avr.c - AVR
- irmp-main-avr-uart.c - AVR with output on UART
- irmp-main-pic-xc8.c - PIC18F4520
- irmp-main-pic-12F1840.c - PIC12F1840
- irmp-main-stm32.c - STM32
- irmp-main-stellaris-arm.c - TI Stellaris LM4F120 Launchpad
- irmp-main-esp8266.c - ESP8266
- irmp-main-mbed.cpp - MBED
- examples/Arduino/Arduino.ino - Teensy 3.x
- irmp-main-chibios.c - ChibiOS
- 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
When using STM32 HAL library define the constants IRSND_Transmit_GPIO_Port und IRSND_Transmit_Pin in STM32Cube (Main.h). Here you don't need to change the constants in irmpconfig.h:
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ARM STM32 with HAL section - don't change here, define IRSND_Transmit_GPIO_Port & IRSND_Transmit_Pin in STM32Cube (Main.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:
/*----------------------------------------------------------------------------
* 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
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. When you want to use another name for the pin, change 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:
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for ChibiOS HAL
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined(_CHIBIOS_HAL_)
# define IRMP_PIN LINE_IR_IN // use pin names as defined in the board config file, prefixed with "LINE_"
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 (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 with the frequency F_INTERRUPTS (10-20kHz). The controller can hardly switch to an energy-saving sleep mode, or must constantly wake up from it. If power consumption is important, e.g. for battery operation, this approach is not optimal.
If IRMP_USE_IDLE_CALL' is activated, IRMP detects if no IR transmission is ongoing and then calls the function irmp_idle(). This is controller-specific and must be provided and linked by the user. The controller can then be put into 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 pinchange interrupt instead. Then the controller can be sent to sleep. If a falling edge is detected on the IR input pin, the pinchange interrupt is deactivated, the timer is activated again 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 pinchange 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 was 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:
/*------------------------------------------------------------------------------------------------------------------------------
* Use ChibiOS Events to signal that valid IR data was received
*------------------------------------------------------------------------------------------------------------------------------
*/
#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 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
#define IRMP_PANASONIC_PROTOCOL 48 // Panasonic (Beamer), start bits similar to KASEIKYO
#define IRMP_MITSU_HEAVY_PROTOCOL 49 // Mitsubishi-Heavy Aircondition, similar timing as Panasonic beamer
#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 Infra Red 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 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!
}
NEW:
Since version 3.2.2 there is the possibility to detect the release of a key. In this case, the IRMP_FLAG_RELEASE flag is set if the remote control in use has set the (repeated) sending of 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) // Erster Frame, flags nicht gesetzt
{
motor_on ();
}
else if (irmp_data.flags & IRMP_FLAG_RELEASE) // Taste wurde losgelassen
{
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 checking IRMP_FLAG_RELEASE:
You must not rely on the fact that irmp_data.command still contains the original command code - here 0x42. There are remote controls (e.g. radio socket transmitters) which themselves send a special key release code when the key is released. So you just check that irmp_data.address matches before testing the flag.
This feature must be enabled explicitly in irmpconfig.h by changing the configuration variable IRMP_ENABLE_RELEASE_DETECTION.
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
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
IRMP supports from version 1.7.0 also IR keyboards, namely the FDC-3402 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 | ||||
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 | |||
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 |
KEY_MAIL | 0x87 | |
Fav. | KEY_FAVORITES | 0x88 |
New Page | KEY_NEW_PAGE | 0x89 |
Setup | KEY_SETUP | 0x8A |
Font | KEY_FONT | 0x8B |
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 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 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 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 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 |
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 pause |
0 Bit | 512µs pause, 512µs pulse |
1 Bit | 512µs pulse, 512µs pause |
Stop-Bit | no stop bit |
Repetition | none |
Keyboard Repetition | After approx. 118ms |
Remarks | An end command (111111111 = 0x1FF) is sent immediately after the button is released. |
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.2.x
Version 3.2.6:
- 2021-01-27: New IR Protocol: MELINERA
- 2021-01-27: Protocol LEGO: Improved timing
- 2021-01-27: Protocol RUWIDO: Improved timing
- 2021-01-27: Protocol NEC: Implemented send of raw NEC reptition frames
Version 3.2.3:
- 2020-08-15: New RF Protokoll: RF_MEDION
Version 3.2.2:
- 2020-07-09: Additional recognition of the radio channels with the RF_X10 protocol
- 2020-07-09: Improved RF frame detection with new stop bit handling.
- 2020-07-09: Improved detection of RF_GEN24 protocols
- 2020-07-09: NEU: Detection if/when a remote control button is released, see chapter Debouncing of Keys.
Version 3.2.1:
- 2020-06-22: Mini bugfix
Version 3.2.0:
- 2020-06-22: Support of 433MHz RF modules
- 2020-06-22: New protocol: RF_GEN24
- 2020-06-22: New protocol: X10
Older Versions
- 2019-08-26: New protocol: METZ
- 2019-08-26: New protocol: ONKYO
- 2018-09-10: New protocol: RCII
- 2018-09-06: Added support of STM32 mit HAL-Library
- 2018-08-30: New option: IRMP_USE_IDLE_CALL
- 2018-08-29: Port to ChibiOS
- 2018-08-29: New protocol: GREE
- 2018-02-19: corrected handling of irmp_flags for invalid frames
- 2017-08-25: New protocol: IRMP16 for transparent 16 bit data communication
- 2016-11-18: Corrected buffer overflow in irmp-main-avr-uart.c
- 2016-09-19: New protocol VINCENT
- 2016-09-09: New protocol Mitsubishi Heavy (air conditioner)
- 2016-09-09: Some modifications for Compiler PIC C18
- 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
- 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-26: Bugfix: deactivated RECS80, RECS80EXT & SIEMENS if interrupts frequency is low
- 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-04-12: New protocol: Bang & Olufsen
- 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-04: New protocol: SAMSUNG32 (Mix aus SAMSUNG & NEC protocol)
- 2010-03-04: Changed some timer tolerances changes of SIRCS- and KASEIKYO
- 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-02-05: Eliminated a conflict between SAMSUNG- and MATSUSHITA protocol
- 2010-01-07: First version
Literature
IR Abstract
- http://www.sbprojects.net/knowledge/ir/index.php
- http://www.epanorama.net/links/irremote.html
- http://www.elektor.de/jahrgang/2008/juni/cc2-avr-projekt-%283%29-unsichtbare-kommandos.497184.lynkx?tab=4
- http://mc.mikrocontroller.com/de/IR-Protokolle.php
SIRCS Protocol
- http://www.sbprojects.net/knowledge/ir/sirc.php
- http://mc.mikrocontroller.com/de/IR-Protokolle.php#SIRCS
- http://www.ustr.net/infrared/sony.shtml
- http://users.telenet.be/davshomepage/sony.htm
- http://picprojects.org.uk/projects/sirc/
- http://www.celadon.com/infrared_protocol/infrared_protocols_samples.pdf
NEC Protocol
- http://www.sbprojects.net/knowledge/ir/nec.php
- http://www.ustr.net/infrared/nec.shtml
- http://www.celadon.com/infrared_protocol/infrared_protocols_samples.pdf
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")
- http://www.mikrocontroller.net/attachment/4246/IR-Protokolle_Diplomarbeit.pdf
- http://www.roboternetz.de/phpBB2/files/entwicklung_und_realisierung_einer_universalinfrarotfernbedienung_mit_timerfunktionen.pdf
RECS80 and RECS80 Extended Protocol
RC5 and RC5x Protocol
- http://www.sbprojects.net/knowledge/ir/rc5.php
- http://mc.mikrocontroller.com/de/IR-Protokolle.php#RC5
- http://users.telenet.be/davshomepage/rc5.htm
- http://www.celadon.com/infrared_protocol/infrared_protocols_samples.pdf
- http://www.opendcc.de/info/rc5/rc5.html
Denon Protocol
- http://www.mikrocontroller.com/de/IR-Protokolle.php#DENON
- http://www.manualowl.com/m/Denon/AVR-3803/Manual/170243
RC6 and RC6A Protocol
Bang & Olufsen
Grundig Protocol
Nokia Protocol
IR60 (SDA2008 and MC14497P)
LEGO Power Functions RC
RCMM Protocol
Other Protocols
- http://www.mikrocontroller.net/attachment/4246/IR-Protokolle_Diplomarbeit.pdf
- http://www.celadon.com/infrared_protocol/infrared_protocols_samples.pdf
- http://www.roboternetz.de/phpBB2/files/entwicklung_und_realisierung_einer_universalinfrarotfernbedienung_mit_timerfunktionen.pdf
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:
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 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!