使用普通IO口作为红外发射和红外接收功能

Dependents:   Nucleo_F411RE_OS_Robot_Tank

Committer:
adaphoto
Date:
Tue Jun 19 12:24:24 2018 +0000
Revision:
0:355a854280cd
??????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
adaphoto 0:355a854280cd 1 /**
adaphoto 0:355a854280cd 2 * IR receiver (Version 0.0.4)
adaphoto 0:355a854280cd 3 *
adaphoto 0:355a854280cd 4 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
adaphoto 0:355a854280cd 5 * http://shinta.main.jp/
adaphoto 0:355a854280cd 6 */
adaphoto 0:355a854280cd 7
adaphoto 0:355a854280cd 8 #include "ReceiverIR.h"
adaphoto 0:355a854280cd 9
adaphoto 0:355a854280cd 10 #define LOCK()
adaphoto 0:355a854280cd 11 #define UNLOCK()
adaphoto 0:355a854280cd 12
adaphoto 0:355a854280cd 13 #define InRange(x,y) ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3)))
adaphoto 0:355a854280cd 14
adaphoto 0:355a854280cd 15 /**
adaphoto 0:355a854280cd 16 * Constructor.
adaphoto 0:355a854280cd 17 *
adaphoto 0:355a854280cd 18 * @param rxpin Pin for receive IR signal.
adaphoto 0:355a854280cd 19 */
adaphoto 0:355a854280cd 20 ReceiverIR::ReceiverIR(PinName rxpin) : evt(rxpin) {
adaphoto 0:355a854280cd 21 init_state();
adaphoto 0:355a854280cd 22 evt.fall(this, &ReceiverIR::isr_fall);
adaphoto 0:355a854280cd 23 evt.rise(this, &ReceiverIR::isr_rise);
adaphoto 0:355a854280cd 24 evt.mode(PullUp);
adaphoto 0:355a854280cd 25 ticker.attach_us(this, &ReceiverIR::isr_wdt, 10 * 1000);
adaphoto 0:355a854280cd 26 }
adaphoto 0:355a854280cd 27
adaphoto 0:355a854280cd 28 /**
adaphoto 0:355a854280cd 29 * Destructor.
adaphoto 0:355a854280cd 30 */
adaphoto 0:355a854280cd 31 ReceiverIR::~ReceiverIR() {
adaphoto 0:355a854280cd 32 }
adaphoto 0:355a854280cd 33
adaphoto 0:355a854280cd 34 /**
adaphoto 0:355a854280cd 35 * Get state.
adaphoto 0:355a854280cd 36 *
adaphoto 0:355a854280cd 37 * @return Current state.
adaphoto 0:355a854280cd 38 */
adaphoto 0:355a854280cd 39 ReceiverIR::State ReceiverIR::getState() {
adaphoto 0:355a854280cd 40 LOCK();
adaphoto 0:355a854280cd 41 State s = work.state;
adaphoto 0:355a854280cd 42 UNLOCK();
adaphoto 0:355a854280cd 43 return s;
adaphoto 0:355a854280cd 44 }
adaphoto 0:355a854280cd 45
adaphoto 0:355a854280cd 46 /**
adaphoto 0:355a854280cd 47 * Get data.
adaphoto 0:355a854280cd 48 *
adaphoto 0:355a854280cd 49 * @param format Pointer to format.
adaphoto 0:355a854280cd 50 * @param buf Buffer of a data.
adaphoto 0:355a854280cd 51 * @param bitlength Bit length of the buffer.
adaphoto 0:355a854280cd 52 *
adaphoto 0:355a854280cd 53 * @return Data bit length.
adaphoto 0:355a854280cd 54 */
adaphoto 0:355a854280cd 55 int ReceiverIR::getData(RemoteIR::Format *format, uint8_t *buf, int bitlength) {
adaphoto 0:355a854280cd 56 LOCK();
adaphoto 0:355a854280cd 57
adaphoto 0:355a854280cd 58 if (bitlength < data.bitcount) {
adaphoto 0:355a854280cd 59 UNLOCK();
adaphoto 0:355a854280cd 60 return -1;
adaphoto 0:355a854280cd 61 }
adaphoto 0:355a854280cd 62
adaphoto 0:355a854280cd 63 const int nbits = data.bitcount;
adaphoto 0:355a854280cd 64 const int nbytes = data.bitcount / 8 + (((data.bitcount % 8) != 0) ? 1 : 0);
adaphoto 0:355a854280cd 65 *format = data.format;
adaphoto 0:355a854280cd 66 for (int i = 0; i < nbytes; i++) {
adaphoto 0:355a854280cd 67 buf[i] = data.buffer[i];
adaphoto 0:355a854280cd 68 }
adaphoto 0:355a854280cd 69
adaphoto 0:355a854280cd 70 init_state();
adaphoto 0:355a854280cd 71
adaphoto 0:355a854280cd 72 UNLOCK();
adaphoto 0:355a854280cd 73 return nbits;
adaphoto 0:355a854280cd 74 }
adaphoto 0:355a854280cd 75
adaphoto 0:355a854280cd 76 void ReceiverIR::init_state(void) {
adaphoto 0:355a854280cd 77 work.c1 = -1;
adaphoto 0:355a854280cd 78 work.c2 = -1;
adaphoto 0:355a854280cd 79 work.c3 = -1;
adaphoto 0:355a854280cd 80 work.d1 = -1;
adaphoto 0:355a854280cd 81 work.d2 = -1;
adaphoto 0:355a854280cd 82 work.state = Idle;
adaphoto 0:355a854280cd 83 data.format = RemoteIR::UNKNOWN;
adaphoto 0:355a854280cd 84 data.bitcount = 0;
adaphoto 0:355a854280cd 85 timer.stop();
adaphoto 0:355a854280cd 86 timer.reset();
adaphoto 0:355a854280cd 87 for (int i = 0; i < sizeof(data.buffer); i++) {
adaphoto 0:355a854280cd 88 data.buffer[i] = 0;
adaphoto 0:355a854280cd 89 }
adaphoto 0:355a854280cd 90 }
adaphoto 0:355a854280cd 91
adaphoto 0:355a854280cd 92 void ReceiverIR::isr_wdt(void) {
adaphoto 0:355a854280cd 93 LOCK();
adaphoto 0:355a854280cd 94 static int cnt = 0;
adaphoto 0:355a854280cd 95 if ((Idle != work.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3) || (0 <= work.d1) || (0 <= work.d2))) {
adaphoto 0:355a854280cd 96 cnt++;
adaphoto 0:355a854280cd 97 if (cnt > 50) {
adaphoto 0:355a854280cd 98 #if 0
adaphoto 0:355a854280cd 99 printf("# WDT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
adaphoto 0:355a854280cd 100 work.c1,
adaphoto 0:355a854280cd 101 work.c2,
adaphoto 0:355a854280cd 102 work.c3,
adaphoto 0:355a854280cd 103 work.d1,
adaphoto 0:355a854280cd 104 work.d2,
adaphoto 0:355a854280cd 105 work.state,
adaphoto 0:355a854280cd 106 data.format,
adaphoto 0:355a854280cd 107 data.bitcount);
adaphoto 0:355a854280cd 108 #endif
adaphoto 0:355a854280cd 109 init_state();
adaphoto 0:355a854280cd 110 cnt = 0;
adaphoto 0:355a854280cd 111 }
adaphoto 0:355a854280cd 112 } else {
adaphoto 0:355a854280cd 113 cnt = 0;
adaphoto 0:355a854280cd 114 }
adaphoto 0:355a854280cd 115 UNLOCK();
adaphoto 0:355a854280cd 116 }
adaphoto 0:355a854280cd 117
adaphoto 0:355a854280cd 118 void ReceiverIR::isr_fall(void) {
adaphoto 0:355a854280cd 119 LOCK();
adaphoto 0:355a854280cd 120 switch (work.state) {
adaphoto 0:355a854280cd 121 case Idle:
adaphoto 0:355a854280cd 122 if (work.c1 < 0) {
adaphoto 0:355a854280cd 123 timer.start();
adaphoto 0:355a854280cd 124 work.c1 = timer.read_us();
adaphoto 0:355a854280cd 125 } else {
adaphoto 0:355a854280cd 126 work.c3 = timer.read_us();
adaphoto 0:355a854280cd 127 int a = work.c2 - work.c1;
adaphoto 0:355a854280cd 128 int b = work.c3 - work.c2;
adaphoto 0:355a854280cd 129 if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 8)) {
adaphoto 0:355a854280cd 130 /*
adaphoto 0:355a854280cd 131 * NEC.
adaphoto 0:355a854280cd 132 */
adaphoto 0:355a854280cd 133 data.format = RemoteIR::NEC;
adaphoto 0:355a854280cd 134 work.state = Receiving;
adaphoto 0:355a854280cd 135 data.bitcount = 0;
adaphoto 0:355a854280cd 136 } else if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 4)) {
adaphoto 0:355a854280cd 137 /*
adaphoto 0:355a854280cd 138 * NEC Repeat.
adaphoto 0:355a854280cd 139 */
adaphoto 0:355a854280cd 140 data.format = RemoteIR::NEC_REPEAT;
adaphoto 0:355a854280cd 141 work.state = Received;
adaphoto 0:355a854280cd 142 data.bitcount = 0;
adaphoto 0:355a854280cd 143 work.c1 = -1;
adaphoto 0:355a854280cd 144 work.c2 = -1;
adaphoto 0:355a854280cd 145 work.c3 = -1;
adaphoto 0:355a854280cd 146 work.d1 = -1;
adaphoto 0:355a854280cd 147 work.d2 = -1;
adaphoto 0:355a854280cd 148 } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 4)) {
adaphoto 0:355a854280cd 149 /*
adaphoto 0:355a854280cd 150 * AEHA.
adaphoto 0:355a854280cd 151 */
adaphoto 0:355a854280cd 152 data.format = RemoteIR::AEHA;
adaphoto 0:355a854280cd 153 work.state = Receiving;
adaphoto 0:355a854280cd 154 data.bitcount = 0;
adaphoto 0:355a854280cd 155 } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 8)) {
adaphoto 0:355a854280cd 156 /*
adaphoto 0:355a854280cd 157 * AEHA Repeat.
adaphoto 0:355a854280cd 158 */
adaphoto 0:355a854280cd 159 data.format = RemoteIR::AEHA_REPEAT;
adaphoto 0:355a854280cd 160 work.state = Received;
adaphoto 0:355a854280cd 161 data.bitcount = 0;
adaphoto 0:355a854280cd 162 work.c1 = -1;
adaphoto 0:355a854280cd 163 work.c2 = -1;
adaphoto 0:355a854280cd 164 work.c3 = -1;
adaphoto 0:355a854280cd 165 work.d1 = -1;
adaphoto 0:355a854280cd 166 work.d2 = -1;
adaphoto 0:355a854280cd 167 } else {
adaphoto 0:355a854280cd 168 init_state();
adaphoto 0:355a854280cd 169 }
adaphoto 0:355a854280cd 170 }
adaphoto 0:355a854280cd 171 break;
adaphoto 0:355a854280cd 172 case Receiving:
adaphoto 0:355a854280cd 173 if (RemoteIR::NEC == data.format) {
adaphoto 0:355a854280cd 174 work.d2 = timer.read_us();
adaphoto 0:355a854280cd 175 int a = work.d2 - work.d1;
adaphoto 0:355a854280cd 176 if (InRange(a, RemoteIR::TUS_NEC * 3)) {
adaphoto 0:355a854280cd 177 data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
adaphoto 0:355a854280cd 178 } else if (InRange(a, RemoteIR::TUS_NEC * 1)) {
adaphoto 0:355a854280cd 179 data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
adaphoto 0:355a854280cd 180 }
adaphoto 0:355a854280cd 181 data.bitcount++;
adaphoto 0:355a854280cd 182 #if 0
adaphoto 0:355a854280cd 183 /*
adaphoto 0:355a854280cd 184 * Length of NEC is always 32 bits.
adaphoto 0:355a854280cd 185 */
adaphoto 0:355a854280cd 186 if (32 <= data.bitcount) {
adaphoto 0:355a854280cd 187 data.state = Received;
adaphoto 0:355a854280cd 188 work.c1 = -1;
adaphoto 0:355a854280cd 189 work.c2 = -1;
adaphoto 0:355a854280cd 190 work.c3 = -1;
adaphoto 0:355a854280cd 191 work.d1 = -1;
adaphoto 0:355a854280cd 192 work.d2 = -1;
adaphoto 0:355a854280cd 193 }
adaphoto 0:355a854280cd 194 #else
adaphoto 0:355a854280cd 195 /*
adaphoto 0:355a854280cd 196 * Set timeout for tail detection automatically.
adaphoto 0:355a854280cd 197 */
adaphoto 0:355a854280cd 198 timeout.detach();
adaphoto 0:355a854280cd 199 timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_NEC * 5);
adaphoto 0:355a854280cd 200 #endif
adaphoto 0:355a854280cd 201 } else if (RemoteIR::AEHA == data.format) {
adaphoto 0:355a854280cd 202 work.d2 = timer.read_us();
adaphoto 0:355a854280cd 203 int a = work.d2 - work.d1;
adaphoto 0:355a854280cd 204 if (InRange(a, RemoteIR::TUS_AEHA * 3)) {
adaphoto 0:355a854280cd 205 data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
adaphoto 0:355a854280cd 206 } else if (InRange(a, RemoteIR::TUS_AEHA * 1)) {
adaphoto 0:355a854280cd 207 data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
adaphoto 0:355a854280cd 208 }
adaphoto 0:355a854280cd 209 data.bitcount++;
adaphoto 0:355a854280cd 210 #if 0
adaphoto 0:355a854280cd 211 /*
adaphoto 0:355a854280cd 212 * Typical length of AEHA is 48 bits.
adaphoto 0:355a854280cd 213 * Please check a specification of your remote controller if you find a problem.
adaphoto 0:355a854280cd 214 */
adaphoto 0:355a854280cd 215 if (48 <= data.bitcount) {
adaphoto 0:355a854280cd 216 data.state = Received;
adaphoto 0:355a854280cd 217 work.c1 = -1;
adaphoto 0:355a854280cd 218 work.c2 = -1;
adaphoto 0:355a854280cd 219 work.c3 = -1;
adaphoto 0:355a854280cd 220 work.d1 = -1;
adaphoto 0:355a854280cd 221 work.d2 = -1;
adaphoto 0:355a854280cd 222 }
adaphoto 0:355a854280cd 223 #else
adaphoto 0:355a854280cd 224 /*
adaphoto 0:355a854280cd 225 * Set timeout for tail detection automatically.
adaphoto 0:355a854280cd 226 */
adaphoto 0:355a854280cd 227 timeout.detach();
adaphoto 0:355a854280cd 228 timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_AEHA * 5);
adaphoto 0:355a854280cd 229 #endif
adaphoto 0:355a854280cd 230 } else if (RemoteIR::SONY == data.format) {
adaphoto 0:355a854280cd 231 work.d1 = timer.read_us();
adaphoto 0:355a854280cd 232 }
adaphoto 0:355a854280cd 233 break;
adaphoto 0:355a854280cd 234 case Received:
adaphoto 0:355a854280cd 235 break;
adaphoto 0:355a854280cd 236 default:
adaphoto 0:355a854280cd 237 break;
adaphoto 0:355a854280cd 238 }
adaphoto 0:355a854280cd 239 UNLOCK();
adaphoto 0:355a854280cd 240 }
adaphoto 0:355a854280cd 241
adaphoto 0:355a854280cd 242 void ReceiverIR::isr_rise(void) {
adaphoto 0:355a854280cd 243 LOCK();
adaphoto 0:355a854280cd 244 switch (work.state) {
adaphoto 0:355a854280cd 245 case Idle:
adaphoto 0:355a854280cd 246 if (0 <= work.c1) {
adaphoto 0:355a854280cd 247 work.c2 = timer.read_us();
adaphoto 0:355a854280cd 248 int a = work.c2 - work.c1;
adaphoto 0:355a854280cd 249 if (InRange(a, RemoteIR::TUS_SONY * 4)) {
adaphoto 0:355a854280cd 250 data.format = RemoteIR::SONY;
adaphoto 0:355a854280cd 251 work.state = Receiving;
adaphoto 0:355a854280cd 252 data.bitcount = 0;
adaphoto 0:355a854280cd 253 } else {
adaphoto 0:355a854280cd 254 static const int MINIMUM_LEADER_WIDTH = 150;
adaphoto 0:355a854280cd 255 if (a < MINIMUM_LEADER_WIDTH) {
adaphoto 0:355a854280cd 256 init_state();
adaphoto 0:355a854280cd 257 }
adaphoto 0:355a854280cd 258 }
adaphoto 0:355a854280cd 259 } else {
adaphoto 0:355a854280cd 260 init_state();
adaphoto 0:355a854280cd 261 }
adaphoto 0:355a854280cd 262 break;
adaphoto 0:355a854280cd 263 case Receiving:
adaphoto 0:355a854280cd 264 if (RemoteIR::NEC == data.format) {
adaphoto 0:355a854280cd 265 work.d1 = timer.read_us();
adaphoto 0:355a854280cd 266 } else if (RemoteIR::AEHA == data.format) {
adaphoto 0:355a854280cd 267 work.d1 = timer.read_us();
adaphoto 0:355a854280cd 268 } else if (RemoteIR::SONY == data.format) {
adaphoto 0:355a854280cd 269 work.d2 = timer.read_us();
adaphoto 0:355a854280cd 270 int a = work.d2 - work.d1;
adaphoto 0:355a854280cd 271 if (InRange(a, RemoteIR::TUS_SONY * 2)) {
adaphoto 0:355a854280cd 272 data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
adaphoto 0:355a854280cd 273 } else if (InRange(a, RemoteIR::TUS_SONY * 1)) {
adaphoto 0:355a854280cd 274 data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
adaphoto 0:355a854280cd 275 }
adaphoto 0:355a854280cd 276 data.bitcount++;
adaphoto 0:355a854280cd 277 #if 0
adaphoto 0:355a854280cd 278 /*
adaphoto 0:355a854280cd 279 * How do I know the correct length? (6bits, 12bits, 15bits, 20bits...)
adaphoto 0:355a854280cd 280 * By a model only?
adaphoto 0:355a854280cd 281 * Please check a specification of your remote controller if you find a problem.
adaphoto 0:355a854280cd 282 */
adaphoto 0:355a854280cd 283 if (12 <= data.bitcount) {
adaphoto 0:355a854280cd 284 data.state = Received;
adaphoto 0:355a854280cd 285 work.c1 = -1;
adaphoto 0:355a854280cd 286 work.c2 = -1;
adaphoto 0:355a854280cd 287 work.c3 = -1;
adaphoto 0:355a854280cd 288 work.d1 = -1;
adaphoto 0:355a854280cd 289 work.d2 = -1;
adaphoto 0:355a854280cd 290 }
adaphoto 0:355a854280cd 291 #else
adaphoto 0:355a854280cd 292 /*
adaphoto 0:355a854280cd 293 * Set timeout for tail detection automatically.
adaphoto 0:355a854280cd 294 */
adaphoto 0:355a854280cd 295 timeout.detach();
adaphoto 0:355a854280cd 296 timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SONY * 4);
adaphoto 0:355a854280cd 297 #endif
adaphoto 0:355a854280cd 298 }
adaphoto 0:355a854280cd 299 break;
adaphoto 0:355a854280cd 300 case Received:
adaphoto 0:355a854280cd 301 break;
adaphoto 0:355a854280cd 302 default:
adaphoto 0:355a854280cd 303 break;
adaphoto 0:355a854280cd 304 }
adaphoto 0:355a854280cd 305 UNLOCK();
adaphoto 0:355a854280cd 306 }
adaphoto 0:355a854280cd 307
adaphoto 0:355a854280cd 308 void ReceiverIR::isr_timeout(void) {
adaphoto 0:355a854280cd 309 LOCK();
adaphoto 0:355a854280cd 310 #if 0
adaphoto 0:355a854280cd 311 printf("# TIMEOUT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
adaphoto 0:355a854280cd 312 work.c1,
adaphoto 0:355a854280cd 313 work.c2,
adaphoto 0:355a854280cd 314 work.c3,
adaphoto 0:355a854280cd 315 work.d1,
adaphoto 0:355a854280cd 316 work.d2,
adaphoto 0:355a854280cd 317 work.state,
adaphoto 0:355a854280cd 318 data.format,
adaphoto 0:355a854280cd 319 data.bitcount);
adaphoto 0:355a854280cd 320 #endif
adaphoto 0:355a854280cd 321 if (work.state == Receiving) {
adaphoto 0:355a854280cd 322 work.state = Received;
adaphoto 0:355a854280cd 323 work.c1 = -1;
adaphoto 0:355a854280cd 324 work.c2 = -1;
adaphoto 0:355a854280cd 325 work.c3 = -1;
adaphoto 0:355a854280cd 326 work.d1 = -1;
adaphoto 0:355a854280cd 327 work.d2 = -1;
adaphoto 0:355a854280cd 328 }
adaphoto 0:355a854280cd 329 UNLOCK();
adaphoto 0:355a854280cd 330 }