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.
Diff: RemoteIR/ReceiverIR.cpp
- Revision:
- 0:5d79cd4ac81d
- Child:
- 1:9370008ac96b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/RemoteIR/ReceiverIR.cpp Fri Aug 13 11:25:40 2010 +0000
@@ -0,0 +1,234 @@
+/**
+ * IR receiver (Version 0.0.1)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#include "ReceiverIR.h"
+
+#define InRange(x,y) ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3)))
+#define IRQ_ENABLE() sem.release(); __enable_irq()
+#define IRQ_DISABLE() __disable_irq(); sem.take()
+
+ReceiverIR::ReceiverIR(PinName rx) : evt(rx) {
+ IRQ_DISABLE();
+ evt.fall(this, &ReceiverIR::isr_fall);
+ evt.rise(this, &ReceiverIR::isr_rise);
+ ticker.attach_us(this, &ReceiverIR::isr_wdt, 1 * 1000);
+ init_state();
+ IRQ_ENABLE();
+}
+
+ReceiverIR::~ReceiverIR() {}
+
+ReceiverIR::State ReceiverIR::getState() {
+ IRQ_DISABLE();
+ State s = data.state;
+ IRQ_ENABLE();
+ return s;
+}
+
+int ReceiverIR::getData(ReceiverIR::Format *format, uint8_t *buf, int bufsiz) {
+ IRQ_DISABLE();
+
+ const int bc = data.bitcount;
+ if (bufsiz < (bc / 8)) {
+ IRQ_ENABLE();
+ return -1;
+ }
+
+ *format = data.format;
+ for (int i = 0; i < (bc / 8); i++) {
+ buf[i] = data.buffer[i];
+ }
+
+ init_state();
+
+ IRQ_ENABLE();
+ return bc;
+}
+
+void ReceiverIR::init_state(void) {
+ work.c1 = -1;
+ work.c2 = -1;
+ work.c3 = -1;
+ work.d1 = -1;
+ work.d2 = -1;
+ data.state = Idle;
+ data.format = UNKNOWN;
+ data.bitcount = 0;
+ timer.stop();
+ timer.reset();
+ for (int i = 0; i < sizeof(data.buffer); i++) {
+ data.buffer[i] = 0;
+ }
+}
+
+void ReceiverIR::isr_wdt(void) {
+ IRQ_DISABLE();
+ static int cnt = 0;
+ if ((Receiving == data.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3))) {
+ cnt++;
+ if (cnt > 500) {
+ printf("# WDT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
+ work.c1,
+ work.c2,
+ work.c3,
+ work.d1,
+ work.d2,
+ data.state,
+ data.format,
+ data.bitcount);
+ init_state();
+ cnt = 0;
+ }
+ } else {
+ cnt = 0;
+ }
+ IRQ_ENABLE();
+}
+
+void ReceiverIR::isr_fall(void) {
+ IRQ_DISABLE();
+ switch (data.state) {
+ case Idle:
+ if (work.c1 < 0) {
+ timer.start();
+ work.c1 = timer.read_us();
+ } else {
+ work.c3 = timer.read_us();
+ int a = work.c2 - work.c1;
+ int b = work.c3 - work.c2;
+ if (InRange(a, TUS_NEC * 16) && InRange(b, TUS_NEC * 8)) {
+ /*
+ * NEC.
+ */
+ data.format = NEC;
+ data.state = Receiving;
+ data.bitcount = 0;
+ } else if (InRange(a, TUS_NEC * 16) && InRange(b, TUS_NEC * 4)) {
+ /*
+ * NEC Repeat.
+ */
+ data.format = NEC;
+ data.state = Received;
+ data.bitcount = 0;
+ } else if (InRange(a, TUS_AEHA * 8) && InRange(b, TUS_AEHA * 4)) {
+ /*
+ * AEHA.
+ */
+ data.format = AEHA;
+ data.state = Receiving;
+ data.bitcount = 0;
+ } else if (InRange(a, TUS_AEHA * 8) && InRange(b, TUS_AEHA * 8)) {
+ /*
+ * AEHA Repeat.
+ */
+ data.format = AEHA;
+ data.state = Received;
+ data.bitcount = 0;
+ } else {
+ init_state();
+ }
+ }
+ break;
+ case Receiving:
+ if (NEC == data.format) {
+ work.d2 = timer.read_us();
+ int a = work.d2 - work.d1;
+ if (InRange(a, TUS_NEC * 3)) {
+ data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
+ } else if (InRange(a, TUS_NEC * 1)) {
+ data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
+ }
+ data.bitcount++;
+ if (32 <= data.bitcount) {
+ data.state = Received;
+ }
+ } else if (AEHA == data.format) {
+ work.d2 = timer.read_us();
+ int a = work.d2 - work.d1;
+ if (InRange(a, TUS_AEHA * 3)) {
+ data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
+ } else if (InRange(a, TUS_AEHA * 1)) {
+ data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
+ }
+ data.bitcount++;
+ /*
+ * Typical length of AEHA is 48 bits.
+ * Please check a specification of your remote controller if you find a problem.
+ */
+ if (48 <= data.bitcount) {
+ data.state = Received;
+ }
+ } else if (SONY == data.format) {
+ work.d1 = timer.read_us();
+ }
+ break;
+ case Received:
+ break;
+ default:
+ break;
+ }
+ IRQ_ENABLE();
+}
+
+void ReceiverIR::isr_rise(void) {
+ IRQ_DISABLE();
+ switch (data.state) {
+ case Idle:
+ if (0 <= work.c1) {
+ work.c2 = timer.read_us();
+ int a = work.c2 - work.c1;
+ if (InRange(a, TUS_SONY * 4)) {
+ data.format = SONY;
+ data.state = Receiving;
+ data.bitcount = 0;
+ } else {
+ static const int MINIMUM_LEADER_WIDTH = 150;
+ if (a < MINIMUM_LEADER_WIDTH) {
+ init_state();
+ }
+ }
+ } else {
+ init_state();
+ }
+ break;
+ case Receiving:
+ if (NEC == data.format) {
+ work.d1 = timer.read_us();
+ } else if (AEHA == data.format) {
+ work.d1 = timer.read_us();
+ } else if (SONY == data.format) {
+ work.d2 = timer.read_us();
+ int a = work.d2 - work.d1;
+ if (InRange(a, TUS_SONY * 2)) {
+ data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
+ } else if (InRange(a, TUS_SONY * 1)) {
+ data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
+ }
+ data.bitcount++;
+ /*
+ * How do we get the correct length?
+ * By a model only?
+ * Please check a specification of your remote controller if you find a problem.
+ */
+ if (12 <= data.bitcount) {
+ data.state = Received;
+ }
+ if (15 <= data.bitcount) {
+ data.state = Received;
+ }
+ if (20 <= data.bitcount) {
+ data.state = Received;
+ }
+ }
+ break;
+ case Received:
+ break;
+ default:
+ break;
+ }
+ IRQ_ENABLE();
+}