RoemoteIR

Committer:
shintamainjp
Date:
Sat Aug 21 11:01:31 2010 +0000
Revision:
4:2304646f6ff5
Parent:
3:dfed23b157e6
Child:
5:e158c85c55ff

        

Who changed what in which revision?

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