00001
00078 #include "irrx.h"
00079 #include "irrx_config.h"
00080 #include <avr/io.h>
00081 #include <avr/interrupt.h>
00082 #include <avr/pgmspace.h>
00083
00084
00085
00086
00087
00088
00089
00090 #if defined(IRRX_PROTOCOL_NEC)
00091 #define IRRX_BITLENGTH_STARTBIT_uS (2400L)
00092 #define IRRX_BITLENGTH_ZERO_uS (3600L)
00093 #define IRRX_BITLENGTH_ONE_uS (1800L)
00094 #define IRRX_STARTBITS 2
00095 #define IRRX_NORMAL_BITS 32
00096 #define IRRX_RECEIVE_TIMEOUT_uS 200000L
00097 #define IRRX_RECEIVE_OK(_irrxbuffer) ((_irrxbuffer.bitbuffer.nec.addr ^ _irrxbuffer.bitbuffer.nec.addr) == 0xFF && \
00098 (_irrxbuffer.bitbuffer.nec.command ^ _irrxbuffer.bitbuffer.nec.command_inv) == 0xFF)
00099
00100 #define IRRX_GETCODE(_irrxbuffer) ((_irrxbuffer.bitbuffer.nec.addr << 8) | _irrxbuffer.bitbuffer.nec.command)
00101 #define IRRX_MSB_FIRST 1
00102 #define IRRX_LSB_FIRST 0
00103
00104 #elif defined(IRRX_PROTOCOL_SONY)
00105
00106 #define IRRX_BITLENGTH_STARTBIT_uS (2400L)
00107 #define IRRX_BITLENGTH_ZERO_uS (1200L)
00108 #define IRRX_BITLENGTH_ONE_uS (1800L)
00109 #define IRRX_STARTBITS 1
00110 #define IRRX_NORMAL_BITS 20L
00111 #define IRRX_RECEIVE_TIMEOUT_uS 50000L
00112 #define IRRX_MSB_FIRST 0
00113 #define IRRX_LSB_FIRST 1
00114
00115 #define IRRX_RECEIVE_OK(_irrxbuffer) (1)
00116 #define IRRX_GETCODE(_irrxbuffer) ((_irrxbuffer.bitbuffer.sony.addr << 12) | _irrxbuffer.bitbuffer.sony.command)
00117
00118 #else
00119 #error IRRX Protocol not defined
00120 #endif
00121
00122
00123
00124
00125
00126
00127
00129 #if defined(__AVR_AT90S4433__)
00130
00131 #define IRRX_INIT_PORTS() {DDRB&=~_BV(PB0);PORTB &= ~_BV(PB0);}
00132 #define IRRX_IS_LOW() (!(PINB & _BV(PB0)))
00133 #define IRRX_POWER_ON() (void)(0)
00134 #define IRRX_POWER_OFF() (void)(0)
00135
00136 #elif defined(__AVR_ATmega8__)
00137
00138 #define IRRX_INIT_PORTS() {DDRB&=~_BV(PB0);PORTB &= ~_BV(PB0);}
00139 #define IRRX_IS_LOW() (!(PINB & _BV(PB0)))
00140 #define IRRX_POWER_ON() PORTB|=_BV(PB7)
00141 #define IRRX_POWER_OFF() PORTB&=~_BV(PB7)
00142
00143 #else
00144 #error "Hardware not configured for IR. Add more CPU definitions."
00145 #endif
00146
00147 #if (0 || defined(IRRX_TRACE_))
00148 #include <stdio.h>
00149 #define IRRX_TRACE1_(str) fprintf(stdout,str);
00150 #define IRRX_TRACE2_(str,p1) fprintf(stdout,str,p1);
00151 #else
00152 #define IRRX_TRACE1_(str) (void)0
00153 #define IRRX_TRACE2_(str,p1) (void)0
00154 #endif
00155
00157 #define IRRX_STATIC_ASSERT(expr) extern char static_assert[ (!!(expr))*2 - 1]
00158
00160 #define IRRX_BIT_COUNT_COMPLETE_MASK 0x80
00161
00163 #define TIMER1_CRITICAL_SECTION_ENTER() { uint8_t saved_sreg = TIMSK; TIMSK &=~ (_BV(TICIE1) | _BV(TOIE1)); {
00164
00166 #define TIMER1_CRITICAL_SECTION_EXIT() } TIMSK = saved_sreg; }
00167
00169 #define IRRX_TIMER1_uS_TO_TICKS(_uS) (((_uS) * (F_CPU / 1000000L)) / (64L))
00170 #define IRRX_TIMER1_ENABLE_INTERRUPTS() TIMSK |= (_BV(TICIE1) | _BV(OCIE1A))
00171 #define IRRX_TIMER1_ENABLE_ICP_RISING_EDGE() {TCCR1B |=_BV(ICES1); TIMSK |= _BV(TICIE1);}
00172 #define IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE() {TCCR1B &=~_BV(ICES1); TIMSK |= _BV(TICIE1);}
00173 #define IRRX_TIMER1_DISABLE_ICP() {TIMSK &=~_BV(TICIE1);}
00174
00175 #define IRRX_TIMER1_START() TCCR1A = 0;TCCR1B |= _BV(ICNC1) | _BV(CS11) | _BV(CS10)
00176 #define IRRX_TIMER1_STOP() TCCR1B &= ~ (_BV(CS12)|_BV(CS11)|_BV(CS10)
00177 #define IRRX_TIMER1_CLEAR_ICP_FLAG() TIFR |=_BV(ICF1)
00178 #define IRRX_TIMER1_RESET() TCNT1 = 0
00179
00180 #define IRRX_RECEIVE_TIMEOUT_TICKS IRRX_TIMER1_uS_TO_TICKS(IRRX_RECEIVE_TIMEOUT_uS)
00181
00182 #define IRRX_BITLENGTH_TICKS_ZERO IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_ZERO_uS)
00183 #define IRRX_BITLENGTH_TICKS_ONE IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_ONE_uS)
00184 #define IRRX_BITLENGTH_TICKS_STARTBIT IRRX_TIMER1_uS_TO_TICKS(IRRX_BITLENGTH_STARTBIT_uS)
00185
00186 #define IRRX_BITLENGTH_TICKS_STARTBIT_MIN (IRRX_BITLENGTH_TICKS_STARTBIT * 3 / 4)
00187 #define IRRX_BITLENGTH_TICKS_STARTBIT_MAX (IRRX_BITLENGTH_TICKS_STARTBIT * 5 / 4)
00188
00189 #define IRRX_BITLENGTH_TICKS_BIT_MIN (IRRX_BITLENGTH_TICKS_ZERO * 3 / 4)
00190 #define IRRX_BITLENGTH_TICKS_BIT_MAX (IRRX_BITLENGTH_TICKS_ONE * 5 / 4)
00191
00192 #define IRRX_BITLENGTH_TICKS_BIT_AVG ((IRRX_BITLENGTH_TICKS_ONE + IRRX_BITLENGTH_TICKS_ZERO) / 2)
00193
00194 IRRX_STATIC_ASSERT(IRRX_BITLENGTH_TICKS_ZERO < IRRX_BITLENGTH_TICKS_ONE);
00195
00196
00197 IRRX_STATIC_ASSERT(IRRX_LSB_FIRST + IRRX_MSB_FIRST == 1);
00198
00199 IRRX_STATIC_ASSERT(IRRX_BITLENGTH_TICKS_ONE >= 10);
00200
00201 IRRX_STATIC_ASSERT(IRRX_BITLENGTH_TICKS_ZERO < 6000);
00202
00203 IRRX_STATIC_ASSERT(IRRX_BITLENGTH_TICKS_STARTBIT_MIN >= 10);
00204
00205 IRRX_STATIC_ASSERT(IRRX_BITLENGTH_TICKS_STARTBIT_MAX < 6000);
00206
00207 IRRX_STATIC_ASSERT(IRRX_RECEIVE_TIMEOUT_TICKS> 100);
00208
00209 IRRX_STATIC_ASSERT(IRRX_RECEIVE_TIMEOUT_TICKS < 65000);
00210
00211
00212 typedef struct
00213 {
00214 uint16_t ticks_one;
00215 uint16_t ticks_zero;
00216 uint16_t ticks_min;
00217 uint16_t ticks_max;
00218 uint16_t ticks_startbit_min;
00219 uint16_t ticks_startbit_max;
00220 uint16_t ticks_receive_timeout;
00221 } irrx_settings_t;
00222
00223 #if defined(IRRX_DEBUG_PARAMETERS)
00224 const irrx_settings_t irrx_settings PROGMEM =
00225 { IRRX_BITLENGTH_TICKS_ONE, IRRX_BITLENGTH_TICKS_ZERO,
00226 IRRX_BITLENGTH_TICKS_BIT_MIN, IRRX_BITLENGTH_TICKS_BIT_MAX,
00227 IRRX_BITLENGTH_TICKS_STARTBIT_MIN,
00228 IRRX_BITLENGTH_TICKS_STARTBIT_MAX, IRRX_RECEIVE_TIMEOUT_TICKS };
00229 #endif //#if defined(IRRX_DEBUG_PARAMETERS)
00230
00231
00232
00233
00234
00235
00236
00237
00239 static volatile irrx_code_t irrx_receivebuffer = 0;
00240
00241 enum
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 };
00256 typedef uint8_t irrx_bitcount_t;
00257
00259 typedef struct
00260 {
00262 irrx_bitcount_t bitcount;
00264 irrx_code_t last_received;
00265 union
00266 {
00267 uint32_t all;
00268 #if defined(IRRX_PROTOCOL_NEC)
00269 struct
00270 {
00271 uint8_t addr;
00272 uint8_t addr_inv;
00273 uint8_t command;
00274 uint8_t command_inv;
00275 }nec;
00276 #endif //#if defined(IRRX_PROTOCOL_NEC)
00277 #if defined(IRRX_PROTOCOL_SONY)
00278 struct
00279 {
00280 uint16_t padding : 12;
00281 uint16_t addr : 9;
00282 uint16_t command : 11;
00283 } sony;
00284 #endif //#if defined(IRRX_PROTOCOL_SONY)
00285 } bitbuffer;
00286 } irrx_internal_t;
00287
00289 static irrx_internal_t irrx_internal;
00290
00291 IRRX_STATIC_ASSERT(sizeof(irrx_internal.bitbuffer) == sizeof(uint32_t));
00292
00293 ISR(TIMER1_COMPA_vect)
00294 {
00296 if (irrx_internal.bitcount != irrx_bitcount_init)
00297 {
00298 IRRX_TRACE1_("k");
00299 }
00300 irrx_internal.bitcount = irrx_bitcount_init;
00301
00302 IRRX_TIMER1_ENABLE_ICP_FALLING_EDGE();
00303 }
00304
00305
00306 ISR(TIMER1_CAPT_vect)
00307 {
00308 uint16_t icr = ICR1;
00309 IRRX_TIMER1_RESET();
00310 IRRX_TIMER1_CLEAR_ICP_FLAG();
00311
00312
00313 OCR1A = IRRX_RECEIVE_TIMEOUT_TICKS;
00314 if (irrx_internal.bitcount == irrx_bitcount_startbit1begin ||
00315 irrx_internal.bitcount == irrx_bitcount_startbit2begin)
00316 {
00317
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
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;
00343 }
00344 else if (IRRX_MSB_FIRST) {
00345 irrx_internal.bitbuffer.all <<= 1;
00346 }
00347
00348
00349
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
00366 if (irrx_internal.bitcount >= irrx_bitcount_lastbit)
00367 {
00368 IRRX_TRACE1_("s");
00369
00370
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 }
00389
00390
00391
00392
00393
00394
00395
00396 void irrx_init(void)
00397 {
00398 IRRX_INIT_PORTS();
00399 IRRX_POWER_OFF();
00400 }
00401
00402 void irrx_power_on(void)
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 }
00411
00412 void irrx_power_off(void)
00413 {
00414 irrx_receivebuffer = IRRX_NO_CODE;
00415 IRRX_POWER_OFF();
00416 }
00417
00418 irrx_code_t irrx_getcode(void)
00419 {
00420 irrx_code_t result;
00421 TIMER1_CRITICAL_SECTION_ENTER()
00422 result = irrx_receivebuffer;
00423 TIMER1_CRITICAL_SECTION_EXIT()
00424 return result;
00425 }