RemotoIR Libraryに、IRC Helicopter Propo の受信処理と、受信パルス幅測定処理を追加したものです。
Dependents: SwiftPropoIR_TestProgram irRawDataDisplay spinner2 LPC1114_ir-spinne_main-propo
Fork of RemoteIR by
ReceiverIR.cpp
- Committer:
- suupen
- Date:
- 2013-08-03
- Revision:
- 13:ec76e93a4d7c
- Parent:
- 12:2379e13b8b34
File content as of revision 13:ec76e93a4d7c:
/** * IR receiver (Version 0.0.4) * * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) * http://shinta.main.jp/ * * ------------------------------------------------------- * 130616 suupen * IRC Helicopter "SWIFT" Propo support * Conditional compilation * "SWIFT_PROTCOL" * "IR_RAW_DATA_ANALYSIS" *-------------------------------------------------------- */ #include "ReceiverIR.h" #define LOCK() #define UNLOCK() #define InRange(x,y) ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3))) /** * Constructor. * * @param rxpin Pin for receive IR signal. */ ReceiverIR::ReceiverIR(PinName rxpin) : evt(rxpin) { init_state(); evt.fall(this, &ReceiverIR::isr_fall); evt.rise(this, &ReceiverIR::isr_rise); evt.mode(PullUp); ticker.attach_us(this, &ReceiverIR::isr_wdt, 10 * 1000); } /** * Destructor. */ ReceiverIR::~ReceiverIR() { } /** * Get state. * * @return Current state. */ ReceiverIR::State ReceiverIR::getState() { LOCK(); State s = work.state; UNLOCK(); return s; } /** * Get data. * * @param format Pointer to format. * @param buf Buffer of a data. * @param bitlength Bit length of the buffer. * * @return Data bit length. */ int ReceiverIR::getData(RemoteIR::Format *format, uint8_t *buf, int bitlength) { LOCK(); if (bitlength < data.bitcount) { UNLOCK(); return -1; } const int nbits = data.bitcount; const int nbytes = data.bitcount / 8 + (((data.bitcount % 8) != 0) ? 1 : 0); *format = data.format; for (int i = 0; i < nbytes; i++) { buf[i] = data.buffer[i]; } init_state(); UNLOCK(); return nbits; } void ReceiverIR::init_state(void) { work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; work.state = Idle; data.format = RemoteIR::UNKNOWN; data.bitcount = 0; timer.stop(); timer.reset(); for (int i = 0; i < sizeof(data.buffer); i++) { data.buffer[i] = 0; } } #ifdef ERRORWAIT void ReceiverIR::errorWait(void) { work.state = ErrorWait; timeout.detach(); timeout.attach_us(this, &ReceiverIR::isr_timeout, 50 * 1000); // 50[ms]wait } #endif //ERRORWAIT void ReceiverIR::isr_wdt(void) { LOCK(); static int cnt = 0; if ((Idle != work.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3) || (0 <= work.d1) || (0 <= work.d2))) { cnt++; if (cnt > 50) { #if 0 printf("# WDT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n", work.c1, work.c2, work.c3, work.d1, work.d2, work.state, data.format, data.bitcount); #endif init_state(); cnt = 0; } } else { cnt = 0; } UNLOCK(); } void ReceiverIR::isr_fall(void) { #ifdef IR_RAW_DATA_ANALYSIS switch (work.state) { case Idle: if (work.c1 < 0) { check.bitcount = 0; check.timecount[check.bitcount++] = 0; } else { check.timecount[check.bitcount++] = timer.read_us() & ~1; } break; case Receiving: if ((check.bitcount < 1000)) { check.timecount[check.bitcount++] = timer.read_us() & ~1; } break; default: break; } #endif //IR_RAW_DATA_ANALYSIS LOCK(); switch (work.state) { case Idle: if (work.c1 < 0) { timer.start(); work.c1 = timer.read_us(); } else { work.c3 = timer.read_us(); int a = work.c2 - work.c1; int b = work.c3 - work.c2; if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 8)) { /* * NEC. */ data.format = RemoteIR::NEC; work.state = Receiving; data.bitcount = 0; } else if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 4)) { /* * NEC Repeat. */ data.format = RemoteIR::NEC_REPEAT; work.state = Received; data.bitcount = 0; work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 4)) { /* * AEHA. */ data.format = RemoteIR::AEHA; work.state = Receiving; data.bitcount = 0; } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 8)) { /* * AEHA Repeat. */ data.format = RemoteIR::AEHA_REPEAT; work.state = Received; data.bitcount = 0; work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; #ifdef SWIFT_PROTCOL } else if (InRange(a, RemoteIR::TUS_SWIFT * 10) && InRange(b, RemoteIR::TUS_SWIFT * 3)) { /* * SWIFT. */ data.format = RemoteIR::SWIFT; work.state = Receiving; data.bitcount = 0; #endif // SWIFT_PROTCOL } else { #ifdef IR_RAW_DATA_ANALYSIS data.format = RemoteIR::UNKNOWN; work.state = Receiving; data.bitcount = 0; #else // ~IR_RAW_DATA_ANALYSIS #ifdef ERRORWAIT errorWait(); #else // ~ERRORWAIT init_state(); #endif // ERRORWAIT #endif // IR_RAW_DATA_ANALYSIS } } break; case Receiving: if (RemoteIR::NEC == data.format) { work.d2 = timer.read_us(); int a = work.d2 - work.d1; if (InRange(a, RemoteIR::TUS_NEC * 3)) { data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); } else if (InRange(a, RemoteIR::TUS_NEC * 1)) { data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); } data.bitcount++; #if 0 /* * Length of NEC is always 32 bits. */ if (32 <= data.bitcount) { data.state = Received; work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; } #else /* * Set timeout for tail detection automatically. */ timeout.detach(); timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_NEC * 5); #endif } else if (RemoteIR::AEHA == data.format) { work.d2 = timer.read_us(); int a = work.d2 - work.d1; if (InRange(a, RemoteIR::TUS_AEHA * 3)) { data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); } else if (InRange(a, RemoteIR::TUS_AEHA * 1)) { data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); } data.bitcount++; #if 0 /* * Typical length of AEHA is 48 bits. * Please check a specification of your remote controller if you find a problem. */ if (48 <= data.bitcount) { data.state = Received; work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; } #else /* * Set timeout for tail detection automatically. */ timeout.detach(); timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_AEHA * 5); #endif } else if (RemoteIR::SONY == data.format) { work.d1 = timer.read_us(); #ifdef SWIFT_PROTCOL } else if (RemoteIR::SWIFT == data.format) { work.d2 = timer.read_us(); int a = work.d2 - work.d1; if (InRange(a, RemoteIR::TUS_SWIFT * 2)) { data.buffer[data.bitcount / 8] |= (1 << (7 - (data.bitcount % 8))); } else if (InRange(a, RemoteIR::TUS_SWIFT * 1)) { data.buffer[data.bitcount / 8] &= ~(1 << (7 - (data.bitcount % 8))); } data.bitcount++; #if 0 /* * Length of SWIFT is always 32 bits. */ if (32 <= data.bitcount) { work.state = Received; work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; } #else /* * Set timeout for tail detection automatically. */ timeout.detach(); timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SWIFT * 5); #endif #endif // SWIFT_PROTCOL #ifdef IR_RAW_DATA_ANALYSIS } else if (RemoteIR::SWIFT == data.format) { /* * Set timeout for tail detection automatically. */ timeout.detach(); timeout.attach_us(this, &ReceiverIR::isr_timeout, (work.c3 - work.c2) * 5); #endif // IR_RAW_DATA_ANALYSIS } break; case Received: break; #ifdef ERRORWAIT case ErrorWait: errorWait(); break; #endif //ERRORWAIT default: break; } UNLOCK(); } void ReceiverIR::isr_rise(void) { #ifdef IR_RAW_DATA_ANALYSIS switch (work.state) { case Idle: case Receiving: check.timecount[check.bitcount++] = timer.read_us() | 1; break; #ifdef ERRORWAIT case ErrorWait: // nothing break; #endif //ERRORWAIT default: break; } #endif //IR_RAW_DATA_ANALYSIS LOCK(); switch (work.state) { case Idle: if (0 <= work.c1) { work.c2 = timer.read_us(); int a = work.c2 - work.c1; if (InRange(a, RemoteIR::TUS_SONY * 4)) { data.format = RemoteIR::SONY; work.state = Receiving; data.bitcount = 0; } else { static const int MINIMUM_LEADER_WIDTH = 150; if (a < MINIMUM_LEADER_WIDTH) { init_state(); } } } else { init_state(); } break; case Receiving: if (RemoteIR::NEC == data.format) { work.d1 = timer.read_us(); } else if (RemoteIR::AEHA == data.format) { work.d1 = timer.read_us(); #ifdef SWIFT_PROTCOL } else if (RemoteIR::SWIFT == data.format) { work.d1 = timer.read_us(); #endif // SWIFT_PROTCOL } else if (RemoteIR::SONY == data.format) { work.d2 = timer.read_us(); int a = work.d2 - work.d1; if (InRange(a, RemoteIR::TUS_SONY * 2)) { data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); } else if (InRange(a, RemoteIR::TUS_SONY * 1)) { data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); } data.bitcount++; #if 0 /* * How do I know the correct length? (6bits, 12bits, 15bits, 20bits...) * By a model only? * Please check a specification of your remote controller if you find a problem. */ if (12 <= data.bitcount) { data.state = Received; work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; } #else /* * Set timeout for tail detection automatically. */ timeout.detach(); timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SONY * 4); #endif } break; case Received: break; #ifdef ERRORWAIT case ErrorWait: // nothing break; #endif //ERRORWAIT default: break; } UNLOCK(); } void ReceiverIR::isr_timeout(void) { LOCK(); #if 0 printf("# TIMEOUT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n", work.c1, work.c2, work.c3, work.d1, work.d2, work.state, data.format, data.bitcount); #endif #ifdef IR_RAW_DATA_ANALYSIS #if 1 //debug for ( int i = 0; i < check.bitcount; i++) { printf("%02d : %06d , %06d , %04d \n", i, check.timecount[i], check.timecount[i + 1], (check.timecount[i + 1] - check.timecount[i])); if( (i % 2) != 0) { printf("\n"); } } printf("\n"); #endif //debug #endif //IR_RAW_DATA_ANALYSIS if (work.state == Receiving) { work.state = Received; work.c1 = -1; work.c2 = -1; work.c3 = -1; work.d1 = -1; work.d2 = -1; } #ifdef ERRORWAIT else if(work.state == ErrorWait){ init_state(); } #endif // ERRORWAIT UNLOCK(); }