愛莉 結城 / Mbed 2 deprecated MARY_IRReceive

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
yuki
Date:
Sun Aug 24 06:58:30 2014 +0000
Parent:
0:7c39876eb334
Commit message:
????;

Changed in this revision

RemoteIR.lib Show diff for this revision Revisions of this file
RemoteIR/ReceiverIR.cpp Show annotated file Show diff for this revision Revisions of this file
RemoteIR/ReceiverIR.h Show annotated file Show diff for this revision Revisions of this file
RemoteIR/RemoteIR.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/RemoteIR.lib	Sat Aug 09 07:24:12 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/shintamainjp/code/RemoteIR/#268cc2ab63bd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RemoteIR/ReceiverIR.cpp	Sun Aug 24 06:58:30 2014 +0000
@@ -0,0 +1,330 @@
+/**
+ * IR receiver (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#include "ReceiverIR.h"
+
+#define LOCK()
+#define UNLOCK()
+
+#define InRange(x,y)   ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3)))
+
+/**
+ * Constructor.
+ *
+ * @param rxpin Pin for receive IR signal.
+ */
+ReceiverIR::ReceiverIR(PinName rxpin) : evt(rxpin) {
+    init_state();
+    evt.fall(this, &ReceiverIR::isr_fall);
+    evt.rise(this, &ReceiverIR::isr_rise);
+    evt.mode(PullUp);
+    ticker.attach_us(this, &ReceiverIR::isr_wdt, 10 * 1000);
+}
+
+/**
+ * Destructor.
+ */
+ReceiverIR::~ReceiverIR() {
+}
+
+/**
+ * Get state.
+ *
+ * @return Current state.
+ */
+ReceiverIR::State ReceiverIR::getState() {
+    LOCK();
+    State s = work.state;
+    UNLOCK();
+    return s;
+}
+
+/**
+ * Get data.
+ *
+ * @param format Pointer to format.
+ * @param buf Buffer of a data.
+ * @param bitlength Bit length of the buffer.
+ *
+ * @return Data bit length.
+ */
+int ReceiverIR::getData(RemoteIR::Format *format, uint8_t *buf, int bitlength) {
+    LOCK();
+
+    if (bitlength < data.bitcount) {
+        UNLOCK();
+        return -1;
+    }
+
+    const int nbits = data.bitcount;
+    const int nbytes = data.bitcount / 8 + (((data.bitcount % 8) != 0) ? 1 : 0);
+    *format = data.format;
+    for (int i = 0; i < nbytes; i++) {
+        buf[i] = data.buffer[i];
+    }
+
+    init_state();
+
+    UNLOCK();
+    return nbits;
+}
+
+void ReceiverIR::init_state(void) {
+    work.c1 = -1;
+    work.c2 = -1;
+    work.c3 = -1;
+    work.d1 = -1;
+    work.d2 = -1;
+    work.state = Idle;
+    data.format = RemoteIR::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) {
+    LOCK();
+    static int cnt = 0;
+    if ((Idle != work.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3) || (0 <= work.d1) || (0 <= work.d2))) {
+        cnt++;
+        if (cnt > 50) {
+#if 0
+            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,
+                   work.state,
+                   data.format,
+                   data.bitcount);
+#endif
+            init_state();
+            cnt = 0;
+        }
+    } else {
+        cnt = 0;
+    }
+    UNLOCK();
+}
+
+void ReceiverIR::isr_fall(void) {
+    LOCK();
+    switch (work.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, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 8)) {
+                    /*
+                     * NEC.
+                     */
+                    data.format = RemoteIR::NEC;
+                    work.state = Receiving;
+                    data.bitcount = 0;
+                } else if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 4)) {
+                    /*
+                     * NEC Repeat.
+                     */
+                    data.format = RemoteIR::NEC_REPEAT;
+                    work.state = Received;
+                    data.bitcount = 0;
+                    work.c1 = -1;
+                    work.c2 = -1;
+                    work.c3 = -1;
+                    work.d1 = -1;
+                    work.d2 = -1;
+                } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 4)) {
+                    /*
+                     * AEHA.
+                     */
+                    data.format = RemoteIR::AEHA;
+                    work.state = Receiving;
+                    data.bitcount = 0;
+                } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 8)) {
+                    /*
+                     * AEHA Repeat.
+                     */
+                    data.format = RemoteIR::AEHA_REPEAT;
+                    work.state = Received;
+                    data.bitcount = 0;
+                    work.c1 = -1;
+                    work.c2 = -1;
+                    work.c3 = -1;
+                    work.d1 = -1;
+                    work.d2 = -1;
+                } else {
+                    init_state();
+                }
+            }
+            break;
+        case Receiving:
+            if (RemoteIR::NEC == data.format) {
+                work.d2 = timer.read_us();
+                int a = work.d2 - work.d1;
+                if (InRange(a, RemoteIR::TUS_NEC * 3)) {
+                    data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
+                } else if (InRange(a, RemoteIR::TUS_NEC * 1)) {
+                    data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
+                }
+                data.bitcount++;
+#if 0
+                /*
+                 * Length of NEC is always 32 bits.
+                 */
+                if (32 <= data.bitcount) {
+                    data.state = Received;
+                    work.c1 = -1;
+                    work.c2 = -1;
+                    work.c3 = -1;
+                    work.d1 = -1;
+                    work.d2 = -1;
+                }
+#else
+                /*
+                 * Set timeout for tail detection automatically.
+                 */
+                timeout.detach();
+                timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_NEC * 5);
+#endif
+            } else if (RemoteIR::AEHA == data.format) {
+                work.d2 = timer.read_us();
+                int a = work.d2 - work.d1;
+                if (InRange(a, RemoteIR::TUS_AEHA * 3)) {
+                    data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
+                } else if (InRange(a, RemoteIR::TUS_AEHA * 1)) {
+                    data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
+                }
+                data.bitcount++;
+#if 0
+                /*
+                 * 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;
+                    work.c1 = -1;
+                    work.c2 = -1;
+                    work.c3 = -1;
+                    work.d1 = -1;
+                    work.d2 = -1;
+                }
+#else
+                /*
+                 * Set timeout for tail detection automatically.
+                 */
+                timeout.detach();
+                timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_AEHA * 5);
+#endif
+            } else if (RemoteIR::SONY == data.format) {
+                work.d1 = timer.read_us();
+            }
+            break;
+        case Received:
+            break;
+        default:
+            break;
+    }
+    UNLOCK();
+}
+
+void ReceiverIR::isr_rise(void) {
+    LOCK();
+    switch (work.state) {
+        case Idle:
+            if (0 <= work.c1) {
+                work.c2 = timer.read_us();
+                int a = work.c2 - work.c1;
+                if (InRange(a, RemoteIR::TUS_SONY * 4)) {
+                    data.format = RemoteIR::SONY;
+                    work.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 (RemoteIR::NEC == data.format) {
+                work.d1 = timer.read_us();
+            } else if (RemoteIR::AEHA == data.format) {
+                work.d1 = timer.read_us();
+            } else if (RemoteIR::SONY == data.format) {
+                work.d2 = timer.read_us();
+                int a = work.d2 - work.d1;
+                if (InRange(a, RemoteIR::TUS_SONY * 2)) {
+                    data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
+                } else if (InRange(a, RemoteIR::TUS_SONY * 1)) {
+                    data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
+                }
+                data.bitcount++;
+#if 0
+                /*
+                 * How do I know the correct length? (6bits, 12bits, 15bits, 20bits...)
+                 * By a model only?
+                 * Please check a specification of your remote controller if you find a problem.
+                 */
+                if (12 <= data.bitcount) {
+                    data.state = Received;
+                    work.c1 = -1;
+                    work.c2 = -1;
+                    work.c3 = -1;
+                    work.d1 = -1;
+                    work.d2 = -1;
+                }
+#else
+                /*
+                 * Set timeout for tail detection automatically.
+                 */
+                timeout.detach();
+                timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SONY * 4);
+#endif
+            }
+            break;
+        case Received:
+            break;
+        default:
+            break;
+    }
+    UNLOCK();
+}
+
+void ReceiverIR::isr_timeout(void) {
+    LOCK();
+#if 0
+    printf("# TIMEOUT [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,
+           work.state,
+           data.format,
+           data.bitcount);
+#endif
+    if (work.state == Receiving) {
+        work.state = Received;
+        work.c1 = -1;
+        work.c2 = -1;
+        work.c3 = -1;
+        work.d1 = -1;
+        work.d2 = -1;
+    }
+    UNLOCK();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RemoteIR/ReceiverIR.h	Sun Aug 24 06:58:30 2014 +0000
@@ -0,0 +1,98 @@
+/**
+ * IR receiver (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#ifndef _RECEIVER_IR_H_
+#define _RECEIVER_IR_H_
+
+#include <mbed.h>
+
+#include "RemoteIR.h"
+
+/**
+ * IR receiver class.
+ */
+class ReceiverIR {
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param rxpin Pin for receive IR signal.
+     */
+    explicit ReceiverIR(PinName rxpin);
+    
+    /**
+     * Destructor.
+     */
+    ~ReceiverIR();
+
+    /**
+     * State.
+     */
+    typedef enum {
+        Idle,
+        Receiving,
+        Received
+    } State;
+    
+    /**
+     * Get state.
+     *
+     * @return Current state.
+     */
+    State getState();
+    
+    /**
+     * Get data.
+     *
+     * @param format Pointer to format.
+     * @param buf Buffer of a data.
+     * @param bitlength Bit length of the buffer.
+     *
+     * @return Data bit length.
+     */
+    int getData(RemoteIR::Format *format, uint8_t *buf, int bitlength);
+    
+private:
+    
+    typedef struct {
+        RemoteIR::Format format;
+        int bitcount;
+        uint8_t buffer[256];
+    } data_t;
+    
+    typedef struct {
+        State state;
+        int c1;
+        int c2;
+        int c3;
+        int d1;
+        int d2;
+    } work_t;
+
+    InterruptIn evt;    /**< Interrupt based input for input. */
+    Timer timer;        /**< Timer for WDT. */
+    Ticker ticker;      /**< Tciker for tick. */
+    Timeout timeout;    /**< Timeout for tail. */
+
+    data_t data;
+    work_t work;
+    
+    void init_state(void);
+
+    void isr_wdt(void);
+    void isr_fall(void);
+    void isr_rise(void);
+    
+    /**
+     * ISR timeout for tail detection.
+     */
+    void isr_timeout(void);
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RemoteIR/RemoteIR.h	Sun Aug 24 06:58:30 2014 +0000
@@ -0,0 +1,31 @@
+/**
+ * IR remote common class (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#ifndef _REMOTE_IR_H_
+#define _REMOTE_IR_H_
+
+class RemoteIR {
+public:
+
+    typedef enum {
+        UNKNOWN,
+        NEC,
+        NEC_REPEAT,
+        AEHA,
+        AEHA_REPEAT,
+        SONY
+    } Format;
+
+    static const int TUS_NEC = 562;
+    static const int TUS_AEHA = 425;
+    static const int TUS_SONY = 600;
+
+private:
+    RemoteIR();
+};
+
+#endif
--- a/main.cpp	Sat Aug 09 07:24:12 2014 +0000
+++ b/main.cpp	Sun Aug 24 06:58:30 2014 +0000
@@ -8,7 +8,8 @@
 //TX dp16 = USBTX RX dp15 = USBRX
 Serial pc(USBTX, USBRX);
 
-int receive(RemoteIR::Format *format, uint8_t *buf, int bufsiz, int timeout = 100) {
+int receive(RemoteIR::Format *format, uint8_t *buf, int bufsiz, int timeout = 200)
+{
     int cnt = 0;
     while (ir_rx.getState() != ReceiverIR::Received) {
         cnt++;
@@ -19,15 +20,15 @@
     return ir_rx.getData(format, buf, bufsiz * 8);
 }
 
-int main() {
+int main()
+{
     pc.baud(9600);
     RemoteIR::Format format;
-    uint8_t buf[64];
+    uint8_t buf[512];
     int bufLength = 0;
     myled1 = myled2 = myled3 = 1;
     while(1) {
         myled1 = 0;
-        memset(buf, 0x00, sizeof(buf));
         bufLength = receive(&format, buf, sizeof(buf));
         if(bufLength < 0) continue;
         myled1 = 1;