irrx/irrx_bitlength.c File Reference

#include "irrx.h"
#include "irrx_config.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

Go to the source code of this file.

Data Structures

struct  irrx_settings_t
struct  irrx_internal_t
 Internal stuff. More...

Defines

#define IRRX_BITLENGTH_STARTBIT_uS   (2400L)
#define IRRX_BITLENGTH_ZERO_uS   (1200L)
#define IRRX_BITLENGTH_ONE_uS   (1800L)
#define IRRX_STARTBITS   1
#define IRRX_NORMAL_BITS   20L
#define IRRX_RECEIVE_TIMEOUT_uS   50000L
#define IRRX_MSB_FIRST   0
#define IRRX_LSB_FIRST   1
#define IRRX_RECEIVE_OK(_irrxbuffer)   (1)
#define IRRX_GETCODE(_irrxbuffer)   ((_irrxbuffer.bitbuffer.sony.addr << 12) | _irrxbuffer.bitbuffer.sony.command)
#define IRRX_TRACE1_(str)   (void)0
 IR receiver is connected to ICP (input capture pin).
#define IRRX_TRACE2_(str, p1)   (void)0
#define IRRX_STATIC_ASSERT(expr)   extern char static_assert[ (!!(expr))*2 - 1]
 Causes a compilation error if expression is not true.
#define IRRX_BIT_COUNT_COMPLETE_MASK   0x80
 Set in bitcount to indicate that reception is complete.
#define TIMER1_CRITICAL_SECTION_ENTER()   { uint8_t saved_sreg = TIMSK; TIMSK &=~ (_BV(TICIE1) | _BV(TOIE1)); {
 Enter critical section.
#define TIMER1_CRITICAL_SECTION_EXIT()   } TIMSK = saved_sreg; }
 Exit critical section.
#define IRRX_TIMER1_uS_TO_TICKS(_uS)   (((_uS) * (F_CPU / 1000000L)) / (64L))
 Init with 1/64 prescaler and input capture enabled.
#define IRRX_TIMER1_ENABLE_INTERRUPTS()   TIMSK |= (_BV(TICIE1) | _BV(OCIE1A))
#define IRRX_TIMER1_ENABLE_ICP_RISING_EDGE()   {TCCR1B |=_BV(ICES1); TIMSK |= _BV(TICIE1);}
#define IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE()   {TCCR1B &=~_BV(ICES1); TIMSK |= _BV(TICIE1);}
#define IRRX_TIMER1_DISABLE_ICP()   {TIMSK &=~_BV(TICIE1);}
#define IRRX_TIMER1_START()   TCCR1A = 0;TCCR1B |= _BV(ICNC1) | _BV(CS11) | _BV(CS10)
#define IRRX_TIMER1_STOP()   TCCR1B &= ~ (_BV(CS12)|_BV(CS11)|_BV(CS10)
#define IRRX_TIMER1_CLEAR_ICP_FLAG()   TIFR |=_BV(ICF1)
#define IRRX_TIMER1_RESET()   TCNT1 = 0
#define IRRX_RECEIVE_TIMEOUT_TICKS   IRRX_TIMER1_uS_TO_TICKS(IRRX_RECEIVE_TIMEOUT_uS)
#define IRRX_BITLENGTH_TICKS_ZERO   IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_ZERO_uS)
#define IRRX_BITLENGTH_TICKS_ONE   IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_ONE_uS)
#define IRRX_BITLENGTH_TICKS_STARTBIT   IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_STARTBIT_uS)
#define IRRX_BITLENGTH_TICKS_STARTBIT_MIN   (IRRX_BITLENGTH_TICKS_STARTBIT * 3 / 4)
#define IRRX_BITLENGTH_TICKS_STARTBIT_MAX   (IRRX_BITLENGTH_TICKS_STARTBIT * 5 / 4)
#define IRRX_BITLENGTH_TICKS_BIT_MIN   (IRRX_BITLENGTH_TICKS_ZERO * 3 / 4)
#define IRRX_BITLENGTH_TICKS_BIT_MAX   (IRRX_BITLENGTH_TICKS_ONE * 5 / 4)
#define IRRX_BITLENGTH_TICKS_BIT_AVG   ((IRRX_BITLENGTH_TICKS_ONE + IRRX_BITLENGTH_TICKS_ZERO) / 2)

Typedefs

typedef uint8_t irrx_bitcount_t

Enumerations

enum  {
  irrx_bitcount_init = 0, irrx_bitcount_startbit1begin = irrx_bitcount_init, irrx_bitcount_startbit1end, irrx_bitcount_startbit2begin = irrx_bitcount_startbit1begin,
  irrx_bitcount_startbit2end = irrx_bitcount_startbit1end, irrx_bitcount_firstbit, irrx_bitcount_lastbit = irrx_bitcount_firstbit + IRRX_NORMAL_BITS
}

Functions

 IRRX_STATIC_ASSERT (IRRX_BITLENGTH_TICKS_ZERO< IRRX_BITLENGTH_TICKS_ONE)
 IRRX_STATIC_ASSERT (IRRX_LSB_FIRST+IRRX_MSB_FIRST==1)
 IRRX_STATIC_ASSERT (IRRX_BITLENGTH_TICKS_ONE >=10)
 IRRX_STATIC_ASSERT (IRRX_BITLENGTH_TICKS_STARTBIT_MIN >=10)
 IRRX_STATIC_ASSERT (IRRX_RECEIVE_TIMEOUT_TICKS > 100)
 IRRX_STATIC_ASSERT (sizeof(irrx_internal.bitbuffer)==sizeof(uint32_t))
 ISR (TIMER1_COMPA_vect)
 ISR (TIMER1_CAPT_vect)
void irrx_init (void)
void irrx_power_on (void)
void irrx_power_off (void)
irrx_code_t irrx_getcode (void)


Define Documentation

#define IRRX_BIT_COUNT_COMPLETE_MASK   0x80

Set in bitcount to indicate that reception is complete.

Definition at line 160 of file irrx_bitlength.c.

#define IRRX_BITLENGTH_ONE_uS   (1800L)

Definition at line 108 of file irrx_bitlength.c.

#define IRRX_BITLENGTH_STARTBIT_uS   (2400L)

_ _ ____ ____ ___ ____ _ | | | / ___|| __ ) |_ _|_ __ | _ \ ___ _ __ ___ ___ | |_ ___ | | | \| _ \ | || '__| | |_) / _ \ '_ ` _ \ / _ \| __/ _ \ | |_| |___) | |_) | | || | | _ < __/ | | | | | (_) | || __/ /|____/|____/ |___|_| |_| |_| |_| |_|/ |

Copyright 2007 J�rgen Birkler jorgen.birkler@gmail.com USB HID device for IR receiver License: GNU GPL v2 (see License.txt) or proprietary (contact author)

Bit length IR receiver (Suitable for Nec remotes, Onkyo, Pioneer, Goldstar, and others)

SIG_OCMP1 is triggered on timeout

SIG_INPUT_CAPTURE1 is triggered on each fall (because the signal is inverted) of the output from the IR receiver.

Basic description of function:

  1. Wait for startbit
  2. Measure length of start bit
  3. Receive bit; measure length from rise-to-rise; ONE is short pulse ZERO is a long pulse
  4. For NEC there are 32 bits: 8 bit address, 8 bit address inversed, 8 bit command, 8 bit command inversed the transmission length is the same due to the inverted bits
Interrupts for one start bit: ________________ ___ ___ ___ ____ __/ / / / / ....

^ ^ ^ ^ ^ ^ | | | | | |

Interrupts for two start bits: ________________ ________________ ___ ___ ___ ____ __/ / / / / / ....

^ ^ ^ ^ ^ ^ ^ | | | | | | |

___ ___ ___ ____________________________________ __/ / / / ^ ^ ^ bc=1 bc=2 bc=3

Timing diagram:

  • T =420 �s to approx 424 �s in the USA and Canada
  • T=454 �s to approx 460 �s in Europe and others
  • The header is 8T high and 8T low
  • ONE is coded 2T high and 6T low
  • ZERO is coded 2T high and 2T low
  • Start bit is 8T high and 8T low break = 6T / 16T * startbit len = 3/8 * startbit len

For Panasonic a ONE is roughly 3.6ms and a ZERO 1.8ms

Main resource:

See for more resources about protocols:

Definition at line 106 of file irrx_bitlength.c.

#define IRRX_BITLENGTH_TICKS_BIT_AVG   ((IRRX_BITLENGTH_TICKS_ONE + IRRX_BITLENGTH_TICKS_ZERO) / 2)

Definition at line 192 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_BITLENGTH_TICKS_BIT_MAX   (IRRX_BITLENGTH_TICKS_ONE * 5 / 4)

Definition at line 190 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_BITLENGTH_TICKS_BIT_MIN   (IRRX_BITLENGTH_TICKS_ZERO * 3 / 4)

Definition at line 189 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_BITLENGTH_TICKS_ONE   IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_ONE_uS)

Definition at line 183 of file irrx_bitlength.c.

#define IRRX_BITLENGTH_TICKS_STARTBIT   IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_STARTBIT_uS)

Definition at line 184 of file irrx_bitlength.c.

#define IRRX_BITLENGTH_TICKS_STARTBIT_MAX   (IRRX_BITLENGTH_TICKS_STARTBIT * 5 / 4)

Definition at line 187 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_BITLENGTH_TICKS_STARTBIT_MIN   (IRRX_BITLENGTH_TICKS_STARTBIT * 3 / 4)

Definition at line 186 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_BITLENGTH_TICKS_ZERO   IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_ZERO_uS)

Definition at line 182 of file irrx_bitlength.c.

#define IRRX_BITLENGTH_ZERO_uS   (1200L)

Definition at line 107 of file irrx_bitlength.c.

#define IRRX_GETCODE ( _irrxbuffer   )     ((_irrxbuffer.bitbuffer.sony.addr << 12) | _irrxbuffer.bitbuffer.sony.command)

Definition at line 116 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_LSB_FIRST   1

Definition at line 113 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_MSB_FIRST   0

Definition at line 112 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_NORMAL_BITS   20L

Definition at line 110 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_RECEIVE_OK ( _irrxbuffer   )     (1)

Definition at line 115 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_RECEIVE_TIMEOUT_TICKS   IRRX_TIMER1_uS_TO_TICKS(IRRX_RECEIVE_TIMEOUT_uS)

Definition at line 180 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_RECEIVE_TIMEOUT_uS   50000L

Definition at line 111 of file irrx_bitlength.c.

#define IRRX_STARTBITS   1

Definition at line 109 of file irrx_bitlength.c.

#define IRRX_STATIC_ASSERT ( expr   )     extern char static_assert[ (!!(expr))*2 - 1]

Causes a compilation error if expression is not true.

Definition at line 157 of file irrx_bitlength.c.

 
#define IRRX_TIMER1_CLEAR_ICP_FLAG (  )     TIFR |=_BV(ICF1)

Definition at line 177 of file irrx_bitlength.c.

Referenced by ISR().

 
#define IRRX_TIMER1_DISABLE_ICP (  )     {TIMSK &=~_BV(TICIE1);}

Definition at line 173 of file irrx_bitlength.c.

 
#define IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE (  )     {TCCR1B &=~_BV(ICES1); TIMSK |= _BV(TICIE1);}

Definition at line 172 of file irrx_bitlength.c.

Referenced by irrx_power_on(), and ISR().

 
#define IRRX_TIMER1_ENABLE_ICP_RISING_EDGE (  )     {TCCR1B |=_BV(ICES1); TIMSK |= _BV(TICIE1);}

Definition at line 171 of file irrx_bitlength.c.

Referenced by ISR().

 
#define IRRX_TIMER1_ENABLE_INTERRUPTS (  )     TIMSK |= (_BV(TICIE1) | _BV(OCIE1A))

Definition at line 170 of file irrx_bitlength.c.

Referenced by irrx_power_on().

 
#define IRRX_TIMER1_RESET (  )     TCNT1 = 0

Definition at line 178 of file irrx_bitlength.c.

Referenced by ISR().

 
#define IRRX_TIMER1_START (  )     TCCR1A = 0;TCCR1B |= _BV(ICNC1) | _BV(CS11) | _BV(CS10)

Definition at line 175 of file irrx_bitlength.c.

Referenced by irrx_power_on().

 
#define IRRX_TIMER1_STOP (  )     TCCR1B &= ~ (_BV(CS12)|_BV(CS11)|_BV(CS10)

Definition at line 176 of file irrx_bitlength.c.

#define IRRX_TIMER1_uS_TO_TICKS ( _uS   )     (((_uS) * (F_CPU / 1000000L)) / (64L))

Init with 1/64 prescaler and input capture enabled.

Definition at line 169 of file irrx_bitlength.c.

#define IRRX_TRACE1_ ( str   )     (void)0

IR receiver is connected to ICP (input capture pin).

Definition at line 152 of file irrx_bitlength.c.

Referenced by ISR().

#define IRRX_TRACE2_ ( str,
p1   )     (void)0

Definition at line 153 of file irrx_bitlength.c.

 
#define TIMER1_CRITICAL_SECTION_ENTER (  )     { uint8_t saved_sreg = TIMSK; TIMSK &=~ (_BV(TICIE1) | _BV(TOIE1)); {

Enter critical section.

Definition at line 163 of file irrx_bitlength.c.

Referenced by irrx_getcode().

 
#define TIMER1_CRITICAL_SECTION_EXIT (  )     } TIMSK = saved_sreg; }

Exit critical section.

Definition at line 166 of file irrx_bitlength.c.

Referenced by irrx_getcode().


Typedef Documentation

typedef uint8_t irrx_bitcount_t

Definition at line 256 of file irrx_bitlength.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
irrx_bitcount_init 
irrx_bitcount_startbit1begin 
irrx_bitcount_startbit1end 
irrx_bitcount_startbit2begin 
irrx_bitcount_startbit2end 
irrx_bitcount_firstbit 
irrx_bitcount_lastbit 

Definition at line 241 of file irrx_bitlength.c.

00242 {
00243   irrx_bitcount_init = 0,
00244   irrx_bitcount_startbit1begin = irrx_bitcount_init,
00245   irrx_bitcount_startbit1end,
00246 #if IRRX_STARTBITS == 1
00247   irrx_bitcount_startbit2begin = irrx_bitcount_startbit1begin,
00248   irrx_bitcount_startbit2end = irrx_bitcount_startbit1end,
00249 #elif IRRX_STARTBITS == 2
00250   irrx_bitcount_startbit2begin,
00251   irrx_bitcount_startbit2end,
00252 #endif
00253   irrx_bitcount_firstbit,
00254   irrx_bitcount_lastbit = irrx_bitcount_firstbit + IRRX_NORMAL_BITS
00255 };


Function Documentation

irrx_code_t irrx_getcode ( void   ) 

Get received ir code Ircode Ir code received

Return values:
IRRX_NO_CODE if not ir code received

Definition at line 418 of file irrx_bitlength.c.

Referenced by main().

00419 {
00420   irrx_code_t result;
00421   TIMER1_CRITICAL_SECTION_ENTER()
00422   result = irrx_receivebuffer;
00423   TIMER1_CRITICAL_SECTION_EXIT()
00424   return result;
00425 }

void irrx_init ( void   ) 

Initialize hardware ports for ir receiver. Call once during reset

Definition at line 396 of file irrx_bitlength.c.

Referenced by main().

00397 {
00398   IRRX_INIT_PORTS();
00399   IRRX_POWER_OFF();
00400 }

void irrx_power_off ( void   ) 

Disables power to the ir receiver and disables interrupts

Definition at line 412 of file irrx_bitlength.c.

00413 {
00414   irrx_receivebuffer = IRRX_NO_CODE;
00415   IRRX_POWER_OFF();
00416 }

void irrx_power_on ( void   ) 

Start reception of ir codes by giving power to ir receiver and init timers and interrupts

Definition at line 402 of file irrx_bitlength.c.

Referenced by main().

00403 {
00404   irrx_internal.bitcount = irrx_bitcount_init;
00405   irrx_receivebuffer = IRRX_NO_CODE;
00406   IRRX_POWER_ON();
00407   IRRX_TIMER1_START();
00408   IRRX_TIMER1_ENABLE_INTERRUPTS();
00409   IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE();
00410 } 

IRRX_STATIC_ASSERT ( sizeof(irrx_internal.bitbuffer)  = =sizeof(uint32_t)  ) 

IRRX_STATIC_ASSERT ( IRRX_RECEIVE_TIMEOUT_TICKS  ,
100   
)

IRRX_STATIC_ASSERT ( IRRX_BITLENGTH_TICKS_STARTBIT_MIN >=  10  ) 

IRRX_STATIC_ASSERT ( IRRX_BITLENGTH_TICKS_ONE >=  10  ) 

IRRX_STATIC_ASSERT ( IRRX_LSB_FIRST+  IRRX_MSB_FIRST = =1  ) 

IRRX_STATIC_ASSERT (  ) 

ISR ( TIMER1_CAPT_vect   ) 

Definition at line 306 of file irrx_bitlength.c.

00307 {
00308   uint16_t icr = ICR1;
00309   IRRX_TIMER1_RESET();
00310   IRRX_TIMER1_CLEAR_ICP_FLAG();
00311   //IRRX_TRACE2_("%d",icr);
00312   //Set timeout ticks for the end of reception (will trigger) 
00313   OCR1A = IRRX_RECEIVE_TIMEOUT_TICKS;
00314   if (irrx_internal.bitcount == irrx_bitcount_startbit1begin || 
00315     irrx_internal.bitcount == irrx_bitcount_startbit2begin)
00316   {
00317     //Set interrupt to detect rest of bits bit (rising edge because signal is inverted)
00318     IRRX_TIMER1_ENABLE_ICP_RISING_EDGE();
00319     IRRX_TRACE1_("A");
00320     irrx_internal.bitcount++;
00321     return;
00322   }
00323   else if (irrx_internal.bitcount == irrx_bitcount_startbit1end || 
00324       irrx_internal.bitcount == irrx_bitcount_startbit2end)
00325   {
00326     IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE();
00327     if (IRRX_BITLENGTH_TICKS_STARTBIT_MIN < icr && icr < IRRX_BITLENGTH_TICKS_STARTBIT_MAX)
00328     {
00329       IRRX_TRACE1_("B");
00330       irrx_receivebuffer = IRRX_NO_CODE;
00331       irrx_internal.bitcount++;
00332       return;
00333     }
00334   }
00335   else {
00336     //Within a valid range?
00337     if (IRRX_BITLENGTH_TICKS_BIT_MIN < icr && icr < IRRX_BITLENGTH_TICKS_BIT_MAX)
00338     {
00339       irrx_internal.bitcount++;
00340 
00341       if (IRRX_LSB_FIRST) {       
00342         irrx_internal.bitbuffer.all >>= 1; //Make room for new bit
00343       }
00344       else if (IRRX_MSB_FIRST) {
00345         irrx_internal.bitbuffer.all <<= 1; //Make room for new bit
00346       }
00347       
00348 
00349       //0 or 1?
00350       if (icr > IRRX_BITLENGTH_TICKS_BIT_AVG)
00351       {
00352         if (IRRX_LSB_FIRST) {       
00353           irrx_internal.bitbuffer.all |= ((uint32_t)1L << (uint32_t)IRRX_NORMAL_BITS);
00354         }
00355         else if (IRRX_MSB_FIRST) {
00356           irrx_internal.bitbuffer.all |= 1;
00357         }
00358         IRRX_TRACE1_("x");
00359       }
00360       else
00361       {
00362         IRRX_TRACE1_("o");
00363       }
00364 
00365       //Last bit?
00366       if (irrx_internal.bitcount >= irrx_bitcount_lastbit)
00367       {
00368         IRRX_TRACE1_("s");
00369 
00370         //Check that ir code looks ok (not all protocol uses this function)
00371         if (IRRX_RECEIVE_OK(irrx_internal))
00372         {
00373           IRRX_TRACE1_("G");
00374           irrx_receivebuffer = IRRX_GETCODE(irrx_internal);
00375         }
00376         else
00377         {
00378           irrx_receivebuffer = IRRX_NO_CODE;
00379         }
00380         irrx_internal.bitcount = irrx_bitcount_init;
00381       }
00382       return;
00383     }
00384   }
00385   IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE();
00386   irrx_internal.bitcount = irrx_bitcount_init;
00387   IRRX_TRACE1_("Y"); 
00388 }

ISR ( TIMER1_COMPA_vect   ) 

Timeout; no receive for some time, reset the bit count

Definition at line 293 of file irrx_bitlength.c.

00294 {
00296   if (irrx_internal.bitcount != irrx_bitcount_init)
00297   {
00298     IRRX_TRACE1_("k");
00299   }
00300   irrx_internal.bitcount = irrx_bitcount_init;
00301   //Set interrupt to detect start of start bit (falling edge because signal is inverted)
00302   IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE();
00303 }


Generated on Fri Oct 30 20:43:20 2009 for USB IR HID Device by  doxygen 1.5.8