Shinichiro Nakamura / Mbed 2 deprecated StarBoardOrangeExample2

Dependencies:   mbed

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();
+}