#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 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:
^ ^ ^ ^ ^ ^ | | | | | |
Interrupts for two start bits: ________________ ________________ ___ ___ ___ ____ __/ / / / / / ....
^ ^ ^ ^ ^ ^ ^ | | | | | | |
___ ___ ___ ____________________________________ __/ / / / ^ ^ ^ bc=1 bc=2 bc=3
Timing diagram:
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) |
#define IRRX_BITLENGTH_TICKS_BIT_MAX (IRRX_BITLENGTH_TICKS_ONE * 5 / 4) |
#define IRRX_BITLENGTH_TICKS_BIT_MIN (IRRX_BITLENGTH_TICKS_ZERO * 3 / 4) |
#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) |
#define IRRX_BITLENGTH_TICKS_STARTBIT_MIN (IRRX_BITLENGTH_TICKS_STARTBIT * 3 / 4) |
#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) |
#define IRRX_LSB_FIRST 1 |
#define IRRX_MSB_FIRST 0 |
#define IRRX_NORMAL_BITS 20L |
#define IRRX_RECEIVE_OK | ( | _irrxbuffer | ) | (1) |
#define IRRX_RECEIVE_TIMEOUT_TICKS IRRX_TIMER1_uS_TO_TICKS(IRRX_RECEIVE_TIMEOUT_uS) |
#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) |
#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);} |
#define IRRX_TIMER1_ENABLE_ICP_RISING_EDGE | ( | ) | {TCCR1B |=_BV(ICES1); TIMSK |= _BV(TICIE1);} |
#define IRRX_TIMER1_ENABLE_INTERRUPTS | ( | ) | TIMSK |= (_BV(TICIE1) | _BV(OCIE1A)) |
#define IRRX_TIMER1_RESET | ( | ) | TCNT1 = 0 |
#define IRRX_TIMER1_START | ( | ) | TCCR1A = 0;TCCR1B |= _BV(ICNC1) | _BV(CS11) | _BV(CS10) |
#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 uint8_t irrx_bitcount_t |
Definition at line 256 of file irrx_bitlength.c.
anonymous enum |
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 };
irrx_code_t irrx_getcode | ( | void | ) |
Get received ir code Ircode Ir code received
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().
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 }