Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of RemoteIR by
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 }
Generated on Thu Jul 21 2022 05:20:31 by
1.7.2
