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