Fixed version of RemoteIR

Fork of RemoteIR by Shinichiro Nakamura

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.d2 = timer.read_us();
00232                 int a = work.d2 - work.d1;
00233                 if (InRange(a, RemoteIR::TUS_SONY * 2)) {
00234                     data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
00235                 } else if (InRange(a, RemoteIR::TUS_SONY * 1)) {
00236                     data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
00237                 }
00238                 data.bitcount++;
00239 #if 0
00240                 /*
00241                  * How do I know the correct length? (6bits, 12bits, 15bits, 20bits...)
00242                  * By a model only?
00243                  * Please check a specification of your remote controller if you find a problem.
00244                  */
00245                 if (12 <= data.bitcount) {
00246                     data.state = Received;
00247                     work.c1 = -1;
00248                     work.c2 = -1;
00249                     work.c3 = -1;
00250                     work.d1 = -1;
00251                     work.d2 = -1;
00252                 }
00253 #else
00254                 /*
00255                  * Set timeout for tail detection automatically.
00256                  */
00257                 timeout.detach();
00258                 timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SONY * 4);
00259 #endif
00260             }
00261             break;
00262         case Received:
00263             break;
00264         default:
00265             break;
00266     }
00267     UNLOCK();
00268 }
00269 
00270 void ReceiverIR::isr_rise(void) {
00271     LOCK();
00272     switch (work.state) {
00273         case Idle:
00274             if (0 <= work.c1) {
00275                 work.c2 = timer.read_us();
00276                 int a = work.c2 - work.c1;
00277                 if (InRange(a, RemoteIR::TUS_SONY * 4)) {
00278                     data.format = RemoteIR::SONY;
00279                     work.state = Receiving;
00280                     data.bitcount = 0;
00281                     work.d1 = timer.read_us();
00282                 } else {
00283                     static const int MINIMUM_LEADER_WIDTH = 150;
00284                     if (a < MINIMUM_LEADER_WIDTH) {
00285                         init_state();
00286                     }
00287                 }
00288             } else {
00289                 init_state();
00290             }
00291             break;
00292         case Receiving:
00293             if (RemoteIR::NEC == data.format) {
00294                 work.d1 = timer.read_us();
00295             } else if (RemoteIR::AEHA == data.format) {
00296                 work.d1 = timer.read_us();
00297             } else if (RemoteIR::SONY == data.format) {
00298                 work.d1 = timer.read_us();
00299             }
00300             break;
00301         case Received:
00302             break;
00303         default:
00304             break;
00305     }
00306     UNLOCK();
00307 }
00308 
00309 void ReceiverIR::isr_timeout(void) {
00310     LOCK();
00311 #if 0
00312     printf("# TIMEOUT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
00313            work.c1,
00314            work.c2,
00315            work.c3,
00316            work.d1,
00317            work.d2,
00318            work.state,
00319            data.format,
00320            data.bitcount);
00321 #endif
00322     if (work.state == Receiving) {
00323         work.state = Received;
00324         work.c1 = -1;
00325         work.c2 = -1;
00326         work.c3 = -1;
00327         work.d1 = -1;
00328         work.d2 = -1;
00329 
00330         if (RemoteIR::SONY == data.format) {
00331             // Fix for SONY empty bits, for example if 31 bits was sended, we need to fill 32nd bit with "1".
00332             // We need to append unreceived bits with "1"s.
00333             int bitsCount = data.bitcount % 8;
00334             if (bitsCount != 0) {
00335                 int bytesCount = data.bitcount / 8;
00336                 for (int i = bitsCount; i < 8; i++) {
00337                     data.buffer[bytesCount] |= (1 << i);
00338                 }
00339             }
00340         }
00341     }
00342     UNLOCK();
00343 }