First release of porting 'Infrared Multiprotocol' library from mikrocontroller.net

Dependents:   IRMP_Receiver

IRMP - Infrared Multiprotocol Decoder

This library is a mbed version of the famous IRMP code, developed by members of the german forum http://mikrocontroller.net. It can receive and analyze a large number of infrared remote codes. In the original version there is also code for an IR transmitter, this will be added to this lib soon.

Base for this initial release is version 2.9.7 from 2015/11. A detailed description for this lib can be found here : https://www.mikrocontroller.net/articles/IRMP_-_english.

The code was originally written for AVR mikrocontrollers and has been ported to different platforms already. It works also great with the mbed target as it can use the unique I/O and ticker code.

Actually, the code uses the static C functions and is not ported to C++ yet to maintain compatibility to the original library. This requres the DigitalIn Pinname setting in the irmpconfig.h.

The required hardware is e.g. just an TSOP31238 (for 38 kHz modulated IR) or similar.

Information

How to use

  • import this library
  • edit irmpconfig.h and turn on the desired protocols
  • change F_INTERRUPTS if necessary, check the protocol table for the minimum necessary frequency
  • search for 'IRMP_PIN' in the irmpconfig and replace with your hardware input

The irmp_ISR() must be called cyclic with a fixed frequency, a simple task for the mbed ticker. In the main program the result is checked by calling irmp_get_data(). This function returns the decoded protocol, address, command and flags like key pressed or released.

Information

Tested platforms

  • simple LPC1347 board, works fine
  • EA LPC4088 QuickStart Board works fine
  • LPCXpresso1549 bad, there is a (known?) issue with slow Ticker ISR processing, ISR consumes >30µs instead of 3 µs
  • STM32F103 board: bad, also known problems with Ticker implementation
  • Test results with other boards are welcome.

Sample code

prints the information about decoded signals to stdout. The ISR contains additional code for performance mesuring which can be omitted in controlling applications.

Import programIRMP_Receiver

Sample code for IRMP library

Sample for decoding and performance test

#include "mbed.h"
#include "irmp.h"

#define LED_ON  0
#define LED_OFF 1

// LED as test output
DigitalOut led(LED1, LED_OFF);
DigitalOut flash(LED2, LED_OFF);

// cyclic interrupt for IRMP ISR worker
Ticker t;

// only for performance test
Timer   timerPerfTest;
int     timeISRMax = 0;
float   timeISRAvg;
int     timeISRAvgSum = 0;
int     countISRCalls = 0;

// this ISR must be called cyclic
void irmpISR(void)
{
    int t1 = timerPerfTest.read_us();               // read performance timer

    irmp_ISR();                                     // call irmp ISR

    int timeISR = timerPerfTest.read_us() - t1;     // calc time spent in worker ISR
    if (timeISR > timeISRMax)                       // store maximum
        timeISRMax = timeISR;
    timeISRAvgSum += timeISR;                       // sum for avg
    countISRCalls++;
}

int main() {
    printf("IRMP on mbed\n");

    led = LED_OFF;
    timerPerfTest.start();

    // irmp_data holds result of received IR code
    IRMP_DATA irmp_data;

    irmp_init();                                                            // initialize irmp
    t.attach_us(&irmpISR, 1E6 / F_INTERRUPTS);                              // call ISR 15.000 / s

    // infinite loop, interrupts will blink PORTD pins and handle UART communications.
    while (1)
    {
        flash = !flash;     // test output. flashes at 15/2 kHz, you will not see it blinking

        // check for received IR commands
        if (irmp_get_data (&irmp_data))
        {
            // ir signal decoded, do something here...
            // irmp_data.protocol is the protocol, see irmp.h
            // irmp_data.address is the address/manufacturer code of ir sender
            // irmp_data.command is the command code
            // irm_data.flags is press/release information
            // irmp_protocol_names[irmp_data.protocol] is the protocol name (if enabled, see irmpconfig.h)
            // printf("proto %d addr %d cmd %d\n", irmp_data.protocol, irmp_data.address, irmp_data.command );

            // sample decoding, turn LED on / off
            if (irmp_data.protocol == IRMP_RC5_PROTOCOL && irmp_data.address == 5)      // old RC5 VCR Remote. TV uses address 0
            {
                if (irmp_data.flags == 0)       // switch only on button press
                {
                    switch (irmp_data.command)
                    {
                    case 0:     // Key '0'
                        led = LED_OFF;
                        break;
                    case 1:     // Key '1'
                        led = LED_ON;
                        break;
                    case 53:        // Key 'play'
                        printf("bring me a beer!\n");
                        break;
                    case 54:        // Key 'stop'
                        timeISRAvg = (float)timeISRAvgSum / countISRCalls;
                        timeISRAvgSum = 0;
                        countISRCalls = 0;
                        printf("ISR max / avg runtime [microseconds] : %d / %5.2f\n", timeISRMax, timeISRAvg);
                        timeISRMax = 0;
                        break;
                    }
                }
            }

            // log to stdout
            printf("proto %d addr %d cmd %d flags %x name %s\n", irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags, irmp_protocol_names[irmp_data.protocol] );
        }
    }

}

irmpsystem.h

Committer:
JojoS
Date:
2016-01-09
Revision:
0:a0715ea739cb

File content as of revision 0:a0715ea739cb:

/*---------------------------------------------------------------------------------------------------------------------------------------------------
 * irmpsystem.h - system specific includes and defines
 *
 * Copyright (c) 2009-2015 Frank Meyer - frank(at)fli4l.de
 *
 * $Id: irmpsystem.h,v 1.21 2015/11/18 08:27:50 fm Exp $
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *---------------------------------------------------------------------------------------------------------------------------------------------------
 */

#ifndef _IRMPSYSTEM_H_
#define _IRMPSYSTEM_H_

#if !defined(_IRMP_H_) && !defined(_IRSND_H_)
#  error please include only irmp.h or irsnd.h, not irmpsystem.h
#endif

#if defined(__18CXX)                                                                // Microchip PIC C18 compiler
#  define PIC_C18
#elif defined(__XC8)                                                                // PIC XC8 compiler
#  include <xc.h>
#  define PIC_C18
#elif defined(__PCM__) || defined(__PCB__) || defined(__PCH__)                      // CCS PIC compiler
#  define PIC_CCS
#elif defined(STM32L1XX_MD) || defined(STM32L1XX_MDP) || defined(STM32L1XX_HD)      // ARM STM32
#  include <stm32l1xx.h>
#  define ARM_STM32
#  define ARM_STM32L1XX
#  define F_CPU (SysCtlClockGet())
#elif defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) \
   || defined(STM32F10X_MD) || defined(STM32F10X_MD_VL) \
   || defined(STM32F10X_HD) || defined(STM32F10X_HD_VL) \
   || defined(STM32F10X_XL) || defined(STM32F10X_CL)                                // ARM STM32
#  include <stm32f10x.h>
#  define ARM_STM32
#  define ARM_STM32F10X
#  define F_CPU (SysCtlClockGet())
#elif defined(STM32F4XX)                                                            // ARM STM32
#  include <stm32f4xx.h>
#  define ARM_STM32
#  define ARM_STM32F4XX
#elif defined(__SDCC_stm8)                                                          // STM8
#  define SDCC_STM8
#elif defined(TARGET_IS_BLIZZARD_RA2)                                               // TI Stellaris (tested on Stellaris Launchpad with Code Composer Studio)
#  define STELLARIS_ARM_CORTEX_M4
#  define F_CPU (SysCtlClockGet())
#elif defined(__xtensa__)
#  include "ets_sys.h"
#  include "osapi.h"
#  include "gpio.h"
#  include "os_type.h"
#  include "c_types.h" 
#  define uint_fast8_t uint8_t
#  define uint_fast16_t uint16_t
#elif defined(TEENSYDUINO) && (defined(__MK20DX256__) || defined(__MK20DX128__))    // Teensy 3.x (tested on Teensy 3.1 in Arduino 1.6.5 / Teensyduino 1.2.5)
#  include <core_pins.h>
#  define TEENSY_ARM_CORTEX_M4
#elif defined(unix) || defined(WIN32) || defined(__APPLE__)                         // Unix/Linux or Windows or Apple
#  define UNIX_OR_WINDOWS
#elif defined(__MBED__)                         									// mbed platform
// #include "mbed.h"																// if mbed.h is used, source must be compiled as cpp
#include "gpio_api.h"
#else
#  define ATMEL_AVR                                                                 // ATMEL AVR
#endif

#include <string.h>

#ifdef UNIX_OR_WINDOWS                                                              // Analyze on Unix/Linux or Windows
#  include <stdio.h>
#  include <stdlib.h>
#  define F_CPU 8000000L
#  define ANALYZE
#  ifdef unix
#    include <stdint.h>
#  else
typedef unsigned char                   uint8_t;
typedef unsigned short                  uint16_t;
#  endif
#endif


#if defined(ATMEL_AVR)
#  include <stdint.h>
#  include <stdio.h>
#  include <avr/io.h>
#  include <util/delay.h>
#  include <avr/pgmspace.h>
#  include <avr/interrupt.h>
#  define IRSND_OC2                     0       // OC2
#  define IRSND_OC2A                    1       // OC2A
#  define IRSND_OC2B                    2       // OC2B
#  define IRSND_OC0                     3       // OC0
#  define IRSND_OC0A                    4       // OC0A
#  define IRSND_OC0B                    5       // OC0B

#  define IRSND_XMEGA_OC0A              0       // OC0A
#  define IRSND_XMEGA_OC0B              1       // OC0B
#  define IRSND_XMEGA_OC0C              2       // OC0C
#  define IRSND_XMEGA_OC0D              3       // OC0D
#  define IRSND_XMEGA_OC1A              4       // OC1A
#  define IRSND_XMEGA_OC1B              5       // OC1B

#elif defined(STELLARIS_ARM_CORTEX_M4)

#  include "inc/hw_ints.h"
#  include "inc/hw_memmap.h"
#  include "inc/hw_types.h"
#  include "inc/hw_gpio.h"
#  include "driverlib/fpu.h"
#  include "driverlib/sysctl.h"
#  include "driverlib/interrupt.h"
#  include "driverlib/gpio.h"
#  include "driverlib/rom.h"
#  include "driverlib/systick.h"
#  include "driverlib/pin_map.h"
#  include "driverlib/timer.h"
#  define PROGMEM
#  define memcpy_P                      memcpy
#  define APP_SYSTICKS_PER_SEC          32

#elif defined(ARM_STM32F10X)

#  include "stm32f10x_gpio.h"
#  include "stm32f10x_rcc.h"
#  include "stm32f10x_tim.h"
#  include "misc.h"
#  define PROGMEM
#  define memcpy_P                      memcpy

#elif defined(SDCC_STM8)

#  include "stm8s.h"
#  define PROGMEM
#  define memcpy_P                      memcpy
#  define __attribute__(x)
#  define uint_fast8_t                  uint8_t
#  define uint_fast16_t                 uint16_t

#elif defined(TEENSY_ARM_CORTEX_M4)
#  define PROGMEM
#  define memcpy_P                      memcpy

#elif defined(__MBED__)
#  define PROGMEM
#  define memcpy_P                      memcpy

#else
#  define PROGMEM
#  define memcpy_P                      memcpy

#endif

#if defined(PIC_CCS) || defined(PIC_C18) || defined(ARM_STM32) || defined(STELLARIS_ARM_CORTEX_M4)
typedef unsigned char                   uint8_t;
typedef unsigned short                  uint16_t;
#endif

#if defined (PIC_C18)                                                               // PIC C18 or XC8 compiler
#  include <p18cxxx.h>                                                              // main PIC18 h file
#ifndef __XC8
#  include <timers.h>                                                               // timer lib
#  include <pwm.h>                                                                  // pwm lib
#endif
#  define IRSND_PIC_CCP1                1                                           // PIC C18 RC2 = PWM1 module
#  define IRSND_PIC_CCP2                2                                           // PIC C18 RC1 = PWM2 module
#endif

#ifndef TRUE
#  define TRUE                          1
#  define FALSE                         0
#endif

typedef struct __attribute__ ((__packed__))
{
    uint8_t                             protocol;                                   // protocol, e.g. NEC_PROTOCOL
    uint16_t                            address;                                    // address
    uint16_t                            command;                                    // command
    uint8_t                             flags;                                      // flags, e.g. repetition
} IRMP_DATA;

#endif // _IRMPSYSTEM_H_