RemoteIR.

Dependents:   RemoteIR_TestProgram SerialGPS_TestProgram StarBoardOrangeExpansion1 Door_Slamming_Device ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ReceiverIR.cpp Source File

ReceiverIR.cpp

00001 /**
00002  * IR receiver (Version 0.0.4)
00003  *
00004  * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
00005  * http://shinta.main.jp/
00006  */
00007 
00008 #include "ReceiverIR.h"
00009 
00010 #define LOCK()
00011 #define UNLOCK()
00012 
00013 #define InRange(x,y)   ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3)))
00014 
00015 /**
00016  * Constructor.
00017  *
00018  * @param rxpin Pin for receive IR signal.
00019  */
00020 ReceiverIR::ReceiverIR(PinName rxpin) : evt(rxpin) {
00021     init_state();
00022     evt.fall(this, &ReceiverIR::isr_fall);
00023     evt.rise(this, &ReceiverIR::isr_rise);
00024     evt.mode(PullUp);
00025     ticker.attach_us(this, &ReceiverIR::isr_wdt, 10 * 1000);
00026 }
00027 
00028 /**
00029  * Destructor.
00030  */
00031 ReceiverIR::~ReceiverIR() {
00032 }
00033 
00034 /**
00035  * Get state.
00036  *
00037  * @return Current state.
00038  */
00039 ReceiverIR::State ReceiverIR::getState() {
00040     LOCK();
00041     State s = work.state;
00042     UNLOCK();
00043     return s;
00044 }
00045 
00046 /**
00047  * Get data.
00048  *
00049  * @param format Pointer to format.
00050  * @param buf Buffer of a data.
00051  * @param bitlength Bit length of the buffer.
00052  *
00053  * @return Data bit length.
00054  */
00055 int ReceiverIR::getData(RemoteIR::Format *format, uint8_t *buf, int bitlength) {
00056     LOCK();
00057 
00058     if (bitlength < data.bitcount) {
00059         UNLOCK();
00060         return -1;
00061     }
00062 
00063     const int nbits = data.bitcount;
00064     const int nbytes = data.bitcount / 8 + (((data.bitcount % 8) != 0) ? 1 : 0);
00065     *format = data.format;
00066     for (int i = 0; i < nbytes; i++) {
00067         buf[i] = data.buffer[i];
00068     }
00069 
00070     init_state();
00071 
00072     UNLOCK();
00073     return nbits;
00074 }
00075 
00076 void ReceiverIR::init_state(void) {
00077     work.c1 = -1;
00078     work.c2 = -1;
00079     work.c3 = -1;
00080     work.d1 = -1;
00081     work.d2 = -1;
00082     work.state = Idle;
00083     data.format = RemoteIR::UNKNOWN;
00084     data.bitcount = 0;
00085     timer.stop();
00086     timer.reset();
00087     for (int i = 0; i < sizeof(data.buffer); i++) {
00088         data.buffer[i] = 0;
00089     }
00090 }
00091 
00092 void ReceiverIR::isr_wdt(void) {
00093     LOCK();
00094     static int cnt = 0;
00095     if ((Idle != work.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3) || (0 <= work.d1) || (0 <= work.d2))) {
00096         cnt++;
00097         if (cnt > 50) {
00098 #if 0
00099             printf("# WDT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
00100                    work.c1,
00101                    work.c2,
00102                    work.c3,
00103                    work.d1,
00104                    work.d2,
00105                    work.state,
00106                    data.format,
00107                    data.bitcount);
00108 #endif
00109             init_state();
00110             cnt = 0;
00111         }
00112     } else {
00113         cnt = 0;
00114     }
00115     UNLOCK();
00116 }
00117 
00118 void ReceiverIR::isr_fall(void) {
00119     LOCK();
00120     switch (work.state) {
00121         case Idle:
00122             if (work.c1 < 0) {
00123                 timer.start();
00124                 work.c1 = timer.read_us();
00125             } else {
00126                 work.c3 = timer.read_us();
00127                 int a = work.c2 - work.c1;
00128                 int b = work.c3 - work.c2;
00129                 if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 8)) {
00130                     /*
00131                      * NEC.
00132                      */
00133                     data.format = RemoteIR::NEC;
00134                     work.state = Receiving;
00135                     data.bitcount = 0;
00136                 } else if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 4)) {
00137                     /*
00138                      * NEC Repeat.
00139                      */
00140                     data.format = RemoteIR::NEC_REPEAT;
00141                     work.state = Received;
00142                     data.bitcount = 0;
00143                     work.c1 = -1;
00144                     work.c2 = -1;
00145                     work.c3 = -1;
00146                     work.d1 = -1;
00147                     work.d2 = -1;
00148                 } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 4)) {
00149                     /*
00150                      * AEHA.
00151                      */
00152                     data.format = RemoteIR::AEHA;
00153                     work.state = Receiving;
00154                     data.bitcount = 0;
00155                 } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 8)) {
00156                     /*
00157                      * AEHA Repeat.
00158                      */
00159                     data.format = RemoteIR::AEHA_REPEAT;
00160                     work.state = Received;
00161                     data.bitcount = 0;
00162                     work.c1 = -1;
00163                     work.c2 = -1;
00164                     work.c3 = -1;
00165                     work.d1 = -1;
00166                     work.d2 = -1;
00167                 } else {
00168                     init_state();
00169                 }
00170             }
00171             break;
00172         case Receiving:
00173             if (RemoteIR::NEC == data.format) {
00174                 work.d2 = timer.read_us();
00175                 int a = work.d2 - work.d1;
00176                 if (InRange(a, RemoteIR::TUS_NEC * 3)) {
00177                     data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
00178                 } else if (InRange(a, RemoteIR::TUS_NEC * 1)) {
00179                     data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
00180                 }
00181                 data.bitcount++;
00182 #if 0
00183                 /*
00184                  * Length of NEC is always 32 bits.
00185                  */
00186                 if (32 <= data.bitcount) {
00187                     data.state = Received;
00188                     work.c1 = -1;
00189                     work.c2 = -1;
00190                     work.c3 = -1;
00191                     work.d1 = -1;
00192                     work.d2 = -1;
00193                 }
00194 #else
00195                 /*
00196                  * Set timeout for tail detection automatically.
00197                  */
00198                 timeout.detach();
00199                 timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_NEC * 5);
00200 #endif
00201             } else if (RemoteIR::AEHA == data.format) {
00202                 work.d2 = timer.read_us();
00203                 int a = work.d2 - work.d1;
00204                 if (InRange(a, RemoteIR::TUS_AEHA * 3)) {
00205                     data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
00206                 } else if (InRange(a, RemoteIR::TUS_AEHA * 1)) {
00207                     data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
00208                 }
00209                 data.bitcount++;
00210 #if 0
00211                 /*
00212                  * Typical length of AEHA is 48 bits.
00213                  * Please check a specification of your remote controller if you find a problem.
00214                  */
00215                 if (48 <= data.bitcount) {
00216                     data.state = Received;
00217                     work.c1 = -1;
00218                     work.c2 = -1;
00219                     work.c3 = -1;
00220                     work.d1 = -1;
00221                     work.d2 = -1;
00222                 }
00223 #else
00224                 /*
00225                  * Set timeout for tail detection automatically.
00226                  */
00227                 timeout.detach();
00228                 timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_AEHA * 5);
00229 #endif
00230             } else if (RemoteIR::SONY == data.format) {
00231                 work.d1 = timer.read_us();
00232             }
00233             break;
00234         case Received:
00235             break;
00236         default:
00237             break;
00238     }
00239     UNLOCK();
00240 }
00241 
00242 void ReceiverIR::isr_rise(void) {
00243     LOCK();
00244     switch (work.state) {
00245         case Idle:
00246             if (0 <= work.c1) {
00247                 work.c2 = timer.read_us();
00248                 int a = work.c2 - work.c1;
00249                 if (InRange(a, RemoteIR::TUS_SONY * 4)) {
00250                     data.format = RemoteIR::SONY;
00251                     work.state = Receiving;
00252                     data.bitcount = 0;
00253                 } else {
00254                     static const int MINIMUM_LEADER_WIDTH = 150;
00255                     if (a < MINIMUM_LEADER_WIDTH) {
00256                         init_state();
00257                     }
00258                 }
00259             } else {
00260                 init_state();
00261             }
00262             break;
00263         case Receiving:
00264             if (RemoteIR::NEC == data.format) {
00265                 work.d1 = timer.read_us();
00266             } else if (RemoteIR::AEHA == data.format) {
00267                 work.d1 = timer.read_us();
00268             } else if (RemoteIR::SONY == data.format) {
00269                 work.d2 = timer.read_us();
00270                 int a = work.d2 - work.d1;
00271                 if (InRange(a, RemoteIR::TUS_SONY * 2)) {
00272                     data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
00273                 } else if (InRange(a, RemoteIR::TUS_SONY * 1)) {
00274                     data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
00275                 }
00276                 data.bitcount++;
00277 #if 0
00278                 /*
00279                  * How do I know the correct length? (6bits, 12bits, 15bits, 20bits...)
00280                  * By a model only?
00281                  * Please check a specification of your remote controller if you find a problem.
00282                  */
00283                 if (12 <= data.bitcount) {
00284                     data.state = Received;
00285                     work.c1 = -1;
00286                     work.c2 = -1;
00287                     work.c3 = -1;
00288                     work.d1 = -1;
00289                     work.d2 = -1;
00290                 }
00291 #else
00292                 /*
00293                  * Set timeout for tail detection automatically.
00294                  */
00295                 timeout.detach();
00296                 timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SONY * 4);
00297 #endif
00298             }
00299             break;
00300         case Received:
00301             break;
00302         default:
00303             break;
00304     }
00305     UNLOCK();
00306 }
00307 
00308 void ReceiverIR::isr_timeout(void) {
00309     LOCK();
00310 #if 0
00311     printf("# TIMEOUT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
00312            work.c1,
00313            work.c2,
00314            work.c3,
00315            work.d1,
00316            work.d2,
00317            work.state,
00318            data.format,
00319            data.bitcount);
00320 #endif
00321     if (work.state == Receiving) {
00322         work.state = Received;
00323         work.c1 = -1;
00324         work.c2 = -1;
00325         work.c3 = -1;
00326         work.d1 = -1;
00327         work.d2 = -1;
00328     }
00329     UNLOCK();
00330 }