IRC Helicopter "HonyBee" Propo decode test program

Dependencies:   RemoteIR mbed

これは、赤外線コントロールヘリコプター"HonyBee"のPropoからの送信データを解析して、PCに表示させるテストプログラムです。 詳しくは、 http://suupen-make.blogspot.jp/2013/06/irc-helicopter-honybeembedtest-program.html を参照してください。

Files at this revision

API Documentation at this revision

Comitter:
suupen
Date:
Sun Jun 23 07:28:06 2013 +0000
Commit message:
IRC Helicopter "HonyBee" Propo decode test program

Changed in this revision

CodecIRPropoHonyBee/CodecHonyBee.h Show annotated file Show diff for this revision Revisions of this file
CodecIRPropoHonyBee/DecodeHonyBee.cpp Show annotated file Show diff for this revision Revisions of this file
CodecIRPropoHonyBee/DecodeHonyBee.h Show annotated file Show diff for this revision Revisions of this file
CodecIRPropoSwift.lib Show annotated file Show diff for this revision Revisions of this file
Propo_RemotoIR.lib Show annotated file Show diff for this revision Revisions of this file
Propo_RemotoIR/ReceiverIR.cpp Show annotated file Show diff for this revision Revisions of this file
Propo_RemotoIR/ReceiverIR.h Show annotated file Show diff for this revision Revisions of this file
Propo_RemotoIR/RemoteIR.h Show annotated file Show diff for this revision Revisions of this file
Propo_RemotoIR/TransmitterIR.cpp Show annotated file Show diff for this revision Revisions of this file
Propo_RemotoIR/TransmitterIR.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
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CodecIRPropoHonyBee/CodecHonyBee.h	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,72 @@
+/**
+ * Codec IR Propo of HonyBee common class
+ * Version 0.0  130623
+ *
+ * Writer:suupen
+ */
+
+#ifndef _CODECHonyBee_H_
+#define _CODECHonyBee_H_
+
+#include <mbed.h>
+
+
+
+class CodecHonyBee {
+public:
+
+    typedef struct{
+        uint8_t count;
+        uint8_t band;   // 1 to 255
+        float slottle;  // 0(min) to 1.0(max)
+        float ladder;   // -1.0(Left) to 1.0(Right)
+        float elevator;  // not use (-1.0(backward) to 1.0(forward))
+        float trim;     // -1.0 to 1.0
+    } normalizePropo_t;
+
+
+
+    typedef struct{
+        uint8_t count;      // recive count [1/1 [recive]/count]
+        uint8_t band;       // 0x0a:A band  0x0b:B 0x0c:C
+        uint8_t slottle;    // 0x00:0 - 0x0e:14
+        uint8_t trim;      // 0x0f:Left 0x01:Right 0x00:neutral
+        int8_t ladder;      // -3:Left3 -2:Left2 -1:Left1 0:Neutral 1:Right1 2:Right2 3:Right3
+        } honyBeePropo_t;
+
+
+static const uint8_t BAND_A = 0x00;
+static const uint8_t BAND_B = 0x01;
+static const uint8_t BAND_C = 0x02;
+
+static const uint8_t SLOTTLE_MIN = 0x00;
+static const uint8_t SLOTTLE_MAX = 0x0e;
+
+//static const int8_t TRIM_MIN = 0;
+//static const int8_t TRIM_MAX = 0x0f;
+static const int8_t TRIM_LEFT = 15;
+static const int8_t TRIM_RIGHT = 1;
+static const int8_t TRIM_NEUTRAL = 0;
+
+static const int8_t LADDER_MIN = -3;
+static const int8_t LADDER_MAX = 3;
+
+#if 0 // not use
+static const int8_t ELEVATOR_MIN = -15;
+static const int8_t ELEVATOR_MAX = 15;
+#endif
+
+private:
+    
+ CodecHonyBee();
+
+
+};
+
+#endif
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CodecIRPropoHonyBee/DecodeHonyBee.cpp	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,172 @@
+/**
+ * IR Propo Decode class
+ * Version 0.0  130623
+ *
+ * Writer:suupen
+ */
+ #include "CodecHonyBee.h"
+ #include "DecodeHonyBee.h"
+ 
+ /**
+ * Constructor DecodeHonyBee
+ *
+ */
+ DecodeHonyBee::DecodeHonyBee(){
+    // nothing
+ }
+ 
+ /**
+ * Destructor.
+ */
+ DecodeHonyBee::~DecodeHonyBee(){
+    // nothing
+ }
+ 
+
+/**
+ * Get HonyBee controller data.
+ *
+ * @param data Pointer to propo recive data.
+ *
+ * @param HonyBee Pointer to HonyBee.
+ *
+ * @return receive answer : ture:recive ok   false:recive ng.
+ */
+bool DecodeHonyBee::decode(uint8_t *data, CodecHonyBee::honyBeePropo_t *honyBee) {
+
+    bool ans = false;
+    uint8_t wk1 = 0,wk2;
+    int8_t ladder;
+    uint8_t dat[3];
+    uint8_t i;
+    
+    // MSB to LSB
+    for(i = 0; i < 8; i++){
+        
+        dat[0] = dat[0] << 1;
+        dat[1] = dat[1] << 1;
+        dat[2] = dat[2] << 1;
+        
+        if(((data[0] >> i) & 0x01) == 0x01){dat[0] |= 0x01;}
+        if(((data[1] >> i) & 0x01) == 0x01){dat[1] |= 0x01;}
+        if(((data[2] >> i) & 0x01) == 0x01){dat[2] |= 0x01;}
+    }
+    
+    // parity calculate
+    for(uint8_t c=0; c < 8; c+=2){
+        wk1 += ((dat[0] >> c) & 0x03);
+        wk1 += ((dat[1] >> c) & 0x03);
+    }
+    wk1 += ((dat[2] >> 6) & 0x02);
+    
+    wk1 &= 0x03;
+    if(wk1 == 0x00){wk1 = 0x03;}
+    else if(wk1 == 0x03){wk1 = 0x00;}
+    
+    wk2 = (dat[2] >> 5) & 0x03;
+    
+    if(wk1 ==  wk2){
+        // parity ok
+        ans =true;
+        honyBee->count++;
+        honyBee->band = (dat[0] >> 2) & 0x03;
+        honyBee->slottle = ((dat[0] << 2) & 0x0c) | ((dat[1] >> 6) & 0x03);
+        honyBee->trim = (dat[1] >> 2) & 0x0f;
+        ladder = ((dat[1] << 1) & 0x06) | ((dat[2] >> 7) & 0x01);
+        if(0x04 == (ladder & 0x04)){ladder |= 0xf8;}
+        honyBee->ladder = ladder;
+    }
+    else{
+        // parity ng
+        // nothing
+        ans = false;
+        honyBee->band = 0x0F;
+    }
+    
+    return ans;
+}
+
+
+/**
+ * Normalize HonyBee data.
+ *
+ * @param buf Pointer to propo recive data.
+ *
+ * @param propo normalize propo data.
+ *
+ * @return receive answer : ture:recive ok   false:recive ng.
+ */
+bool DecodeHonyBee::normalize(uint8_t *buf, CodecHonyBee::normalizePropo_t *propo) {
+    bool ans = false;
+    bool decodeCheck =false;
+    
+    CodecHonyBee::honyBeePropo_t HonyBee;
+    decodeCheck = DecodeHonyBee::decode(buf, &HonyBee);
+    
+    if(decodeCheck == true){
+        ans = true;
+     
+        propo->count++;// = HonyBee.count;
+        
+        switch(HonyBee.band){
+        case CodecHonyBee::BAND_A:
+            propo->band = 1;
+            break;
+        case CodecHonyBee::BAND_B:
+            propo->band = 2;
+            break;
+        case CodecHonyBee::BAND_C:
+            propo->band = 3;
+            break;
+        default:
+            propo->band = 0;
+            break;
+        }
+        
+        if(HonyBee.slottle > CodecHonyBee::SLOTTLE_MAX){HonyBee.slottle = CodecHonyBee::SLOTTLE_MAX;}
+        propo->slottle = (float)HonyBee.slottle / CodecHonyBee::SLOTTLE_MAX;
+        
+        if(HonyBee.ladder >= 0){
+            if(HonyBee.ladder > CodecHonyBee::LADDER_MAX){HonyBee.ladder = CodecHonyBee::LADDER_MAX;}
+            propo->ladder = (float)HonyBee.ladder / CodecHonyBee::LADDER_MAX;
+        }
+        else{
+            if(HonyBee.ladder < CodecHonyBee::LADDER_MIN){HonyBee.ladder = CodecHonyBee::LADDER_MIN;}        
+            propo->ladder = -((float)HonyBee.ladder / CodecHonyBee::LADDER_MIN);
+        }
+
+#if 0 // not use        
+        if(HonyBee.elevator >= 0){
+            if(HonyBee.elevator > CodecHonyBee::ELEVATOR_MAX){HonyBee.elevator = CodecHonyBee::ELEVATOR_MAX;}       
+            propo->elevator = (float)HonyBee.elevator / CodecHonyBee::ELEVATOR_MAX;
+        }
+        else{
+            if(HonyBee.elevator < CodecHonyBee::ELEVATOR_MIN){HonyBee.elevator = CodecHonyBee::ELEVATOR_MIN;}
+            propo->elevator = -((float)HonyBee.elevator / CodecHonyBee::ELEVATOR_MIN);
+        }
+#endif // not use
+        
+        switch (HonyBee.trim){
+        case CodecHonyBee::TRIM_LEFT:
+            propo->trim = -1.0;
+            break;
+        case CodecHonyBee::TRIM_RIGHT:
+            propo->trim = 1.0;
+            break;
+        default:
+//      case CodecHonyBee::TRIM_NEUTRAL:
+            propo->trim = 0.0;
+            break;        
+        }
+  
+    }
+    else{
+        // NG
+        ans = false;
+    }
+
+    return ans;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CodecIRPropoHonyBee/DecodeHonyBee.h	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,63 @@
+/**
+ * Decode IR Propo HonyBee class
+ *  Version 0.0     130623
+ *
+ * Writer:suupen
+ */
+
+#ifndef _DECODEHonyBee_H_
+#define _DECODEHonyBee_H_
+
+#include <mbed.h>
+#include "CodecHonyBee.h"
+
+
+/**
+ * Decode class.
+ */
+class DecodeHonyBee {
+public:
+
+
+/**
+ * Constructor
+ */
+  DecodeHonyBee();
+  
+/**
+ * Destructor.
+ */
+  ~DecodeHonyBee();
+    
+/**
+ * Get HonyBee propo analysis data.
+ *
+ * @param data IR recive data
+ *
+ * @param HonyBee Pointer to HonyBee.
+ *
+ * @return receive answer : ture:recive ok   false:recive ng.
+ */
+    bool decode(uint8_t *data, CodecHonyBee::honyBeePropo_t *HonyBee);
+
+/**
+ * Normalize HonyBee data.
+ *
+ * @param buf Pointer to propo recive data.
+ *
+ * @param propo normalize propo data.
+ *
+ * @return receive answer : ture:recive ok   false:recive ng.
+ */
+bool normalize(uint8_t *buf, CodecHonyBee::normalizePropo_t *propo);
+
+private:
+    
+ 
+
+
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CodecIRPropoSwift.lib	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,1 @@
+CodecIRPropoSwift#000000000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Propo_RemotoIR.lib	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/shintamainjp/code/RemoteIR/#268cc2ab63bd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Propo_RemotoIR/ReceiverIR.cpp	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,448 @@
+/**
+ * IR receiver (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ *
+ * -------------------------------------------------------
+ * 130616 suupen
+ * IRC Helicopter "SWIFT" Propo support
+ *  Conditional compilation 
+ *      "SWIFT_PROTCOL"
+ *      "IR_RAW_DATA_ANALYSIS"
+ *--------------------------------------------------------
+ */
+
+#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) {
+
+#ifdef IR_RAW_DATA_ANALYSIS
+    switch (work.state) {
+    case Idle:
+        if (work.c1 < 0){
+            check.bitcount = 0;
+            check.timecount[check.bitcount++] = 0;
+        } else {
+            check.timecount[check.bitcount++] = timer.read_us() & ~1;
+        }
+        break;
+    case Receiving:
+ 
+        if ((check.bitcount < 1000))  { 
+            check.timecount[check.bitcount++] = timer.read_us() & ~1; 
+        }
+        break;
+    default:
+        break;
+    }
+#endif //IR_RAW_DATA_ANALYSIS
+
+    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;
+#ifdef SWIFT_PROTCOL
+                } else if (InRange(a, RemoteIR::TUS_SWIFT * 10) && InRange(b, RemoteIR::TUS_SWIFT * 3)) {
+                    /*
+                     * SWIFT.
+                     */
+                    data.format = RemoteIR::SWIFT;
+                    work.state = Receiving;
+                    data.bitcount = 0;
+#endif  // SWIFT_PROTCOL                    
+                } else {
+#ifdef IR_RAW_DATA_ANALYSIS
+                    data.format = RemoteIR::UNKNOWN;
+                    work.state = Receiving;
+                    data.bitcount = 0;
+#else // ~IR_RAW_DATA_ANALYSIS                        
+                    init_state();
+#endif // IR_RAW_DATA_ANALYSIS                
+                 }
+            }
+            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();
+#ifdef SWIFT_PROTCOL            
+            } else if (RemoteIR::SWIFT == data.format) {
+                work.d2 = timer.read_us();
+                int a = work.d2 - work.d1;
+                if (InRange(a, RemoteIR::TUS_SWIFT * 2)) {
+                    data.buffer[data.bitcount / 8] |= (1 << (7 - (data.bitcount % 8)));
+                } else if (InRange(a, RemoteIR::TUS_SWIFT * 1)) {
+                    data.buffer[data.bitcount / 8] &= ~(1 << (7 - (data.bitcount % 8)));
+                }
+                data.bitcount++;
+#if 0
+                /*
+                 * Length of SWIFT is always 32 bits.
+                 */
+                if (32 <= data.bitcount) {
+                    work.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_SWIFT * 5);
+#endif
+#endif  // SWIFT_PROTCOL
+
+#ifdef IR_RAW_DATA_ANALYSIS
+            } else if (RemoteIR::SWIFT == data.format) {
+                 /*
+                 * Set timeout for tail detection automatically.
+                 */
+                timeout.detach();
+                timeout.attach_us(this, &ReceiverIR::isr_timeout, (work.c3 - work.c2) * 5);
+#endif // IR_RAW_DATA_ANALYSIS
+            }
+            break;
+        case Received:
+            break;
+        default:
+            break;
+    }
+    UNLOCK();
+}
+
+void ReceiverIR::isr_rise(void) {
+
+#ifdef IR_RAW_DATA_ANALYSIS
+    switch (work.state) {
+    case Idle:
+    case Receiving:
+        check.timecount[check.bitcount++] = timer.read_us() | 1;
+        break;
+    default:
+        break;
+    }
+#endif //IR_RAW_DATA_ANALYSIS
+
+    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();
+#ifdef SWIFT_PROTCOL
+            } else if (RemoteIR::SWIFT == data.format) {
+                work.d1 = timer.read_us();
+#endif // SWIFT_PROTCOL
+            } 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
+
+#ifdef IR_RAW_DATA_ANALYSIS
+#if 1 //debug
+    for ( int i = 0; i < check.bitcount; i++){
+        printf("%02d : %06d , %06d , %04d \n",
+            i,
+            check.timecount[i],
+            check.timecount[i + 1],
+            (check.timecount[i + 1] - check.timecount[i]));
+            
+        if( (i % 2) != 0){printf("\n");}
+     }
+    printf("\n");
+#endif //debug
+#endif //IR_RAW_DATA_ANALYSIS
+
+    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/Propo_RemotoIR/ReceiverIR.h	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,120 @@
+/**
+ * IR receiver (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ *
+ * -------------------------------------------------------
+ * 130616 suupen
+ * IRC Helicopter "SWIFT" Propo support
+ *  Conditional compilation 
+ *      "SWIFT_PROTCOL"
+ *      "IR_RAW_DATA_ANALYSIS"
+ *--------------------------------------------------------
+ */
+
+#ifndef _RECEIVER_IR_H_
+#define _RECEIVER_IR_H_
+
+#include <mbed.h>
+
+#include "RemoteIR.h"
+
+//#define IR_RAW_DATA_ANALYSIS
+
+/**
+ * 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[64];
+    } data_t;
+    
+    typedef struct {
+        State state;
+        int c1;
+        int c2;
+        int c3;
+        int d1;
+        int d2;
+    } work_t;
+    
+ #ifdef IR_RAW_DATA_ANALYSIS
+    typedef struct {
+        State state;
+        int timecount[1000];   // Hi,Lo count (1/1 [us]/count)
+        int bitcount;
+    } check_t;
+#endif //IR_RAW_DATA_ANALYSIS
+
+    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;
+ #ifdef IR_RAW_DATA_ANALYSIS
+    check_t check;
+#endif //IR_RAW_DATA_ANALYSIS
+   
+    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/Propo_RemotoIR/RemoteIR.h	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,48 @@
+/**
+ * IR remote common class (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ *
+ * -------------------------------------------------------
+ * 130616 suupen
+ * IRC Helicopter "SWIFT" Propo support
+ *  Conditional compilation 
+ *      "SWIFT_PROTCOL"
+ *      "IR_RAW_DATA_ANALYSIS"
+ *--------------------------------------------------------
+ */
+
+#ifndef _REMOTE_IR_H_
+#define _REMOTE_IR_H_
+
+#define SWIFT_PROTCOL   // IRC Helicopter SWIFT protcol
+
+
+class RemoteIR {
+public:
+
+    typedef enum {
+        UNKNOWN,
+        NEC,
+        NEC_REPEAT,
+        AEHA,
+        AEHA_REPEAT,
+        SONY,
+#ifdef SWIFT_PROTCOL
+        SWIFT,
+#endif // SWIFT_PROTCOL
+     } Format;
+
+    static const int TUS_NEC = 562;
+    static const int TUS_AEHA = 425;
+    static const int TUS_SONY = 600;
+#ifdef SWIFT_PROTCOL
+    static const int TUS_SWIFT = 350;
+#endif // SWIFT_PROTCOL
+
+private:
+    RemoteIR();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Propo_RemotoIR/TransmitterIR.cpp	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,300 @@
+/**
+ * IR transmitter (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#include "TransmitterIR.h"
+
+#define LOCK()
+#define UNLOCK()
+
+/**
+ * Constructor.
+ *
+ * @param txpin Pin for transmit IR signal.
+ */
+TransmitterIR::TransmitterIR(PinName txpin) : tx(txpin) {
+    tx.write(0.0);
+    tx.period_us(26.3);
+
+    work.state = Idle;
+    work.bitcount = 0;
+    work.leader = 0;
+    work.data = 0;
+    work.trailer = 0;
+
+    data.format = RemoteIR::UNKNOWN;
+    data.bitlength = 0;
+}
+
+/**
+ * Destructor.
+ */
+TransmitterIR::~TransmitterIR() {
+}
+
+/**
+ * Get state.
+ *
+ * @return Current state.
+ */
+TransmitterIR::State TransmitterIR::getState(void) {
+    LOCK();
+    State s = work.state;
+    UNLOCK();
+    return s;
+}
+
+/**
+ * Set data.
+ *
+ * @param format Format.
+ * @param buf Buffer of a data.
+ * @param bitlength Bit length of the data.
+ *
+ * @return Data bit length.
+ */
+int TransmitterIR::setData(RemoteIR::Format format, uint8_t *buf, int bitlength) {
+    LOCK();
+    if (work.state != Idle) {
+        UNLOCK();
+        return -1;
+    }
+
+    work.state = Leader;
+    work.bitcount = 0;
+    work.leader = 0;
+    work.data = 0;
+    work.trailer = 0;
+
+    data.format = format;
+    data.bitlength = bitlength;
+    const int n = bitlength / 8 + (((bitlength % 8) != 0) ? 1 : 0);
+    for (int i = 0; i < n; i++) {
+        data.buffer[i] = buf[i];
+    }
+
+    switch (format) {
+        case RemoteIR::NEC:
+            ticker.detach();
+            ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_NEC);
+            break;
+        case RemoteIR::AEHA:
+            ticker.detach();
+            ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_AEHA);
+            break;
+        case RemoteIR::SONY:
+            ticker.detach();
+            ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_SONY);
+            break;
+    }
+
+    UNLOCK();
+    return bitlength;
+}
+
+void TransmitterIR::tick(void) {
+    LOCK();
+    switch (work.state) {
+        case Idle:
+            work.bitcount = 0;
+            work.leader = 0;
+            work.data = 0;
+            work.trailer = 0;
+            break;
+        case Leader:
+            if (data.format == RemoteIR::NEC) {
+                /*
+                 * NEC.
+                 */
+                static const int LEADER_NEC_HEAD = 16;
+                static const int LEADER_NEC_TAIL = 8;
+                if (work.leader < LEADER_NEC_HEAD) {
+                    tx.write(0.5);
+                } else {
+                    tx.write(0.0);
+                }
+                work.leader++;
+                if ((LEADER_NEC_HEAD + LEADER_NEC_TAIL) <= work.leader) {
+                    work.state = Data;
+                }
+            } else if (data.format == RemoteIR::AEHA) {
+                /*
+                 * AEHA.
+                 */
+                static const int LEADER_AEHA_HEAD = 8;
+                static const int LEADER_AEHA_TAIL = 4;
+                if (work.leader < LEADER_AEHA_HEAD) {
+                    tx.write(0.5);
+                } else {
+                    tx.write(0.0);
+                }
+                work.leader++;
+                if ((LEADER_AEHA_HEAD + LEADER_AEHA_TAIL) <= work.leader) {
+                    work.state = Data;
+                }
+            } else if (data.format == RemoteIR::SONY) {
+                /*
+                 * SONY.
+                 */
+                static const int LEADER_SONY_HEAD = 4;
+                static const int LEADER_SONY_TAIL = 0;
+                if (work.leader < LEADER_SONY_HEAD) {
+                    tx.write(0.5);
+                } else {
+                    tx.write(0.0);
+                }
+                work.leader++;
+                if ((LEADER_SONY_HEAD + LEADER_SONY_TAIL) <= work.leader) {
+                    work.state = Data;
+                }
+            } else {
+            }
+            break;
+        case Data:
+            if (data.format == RemoteIR::NEC) {
+                /*
+                 * NEC.
+                 */
+                if (work.data == 0) {
+                    tx.write(0.5);
+                    work.data++;
+                } else {
+                    tx.write(0.0);
+                    if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
+                        if (3 <= work.data) {
+                            work.bitcount++;
+                            work.data = 0;
+                        } else {
+                            work.data++;
+                        }
+                    } else {
+                        if (1 <= work.data) {
+                            work.bitcount++;
+                            work.data = 0;
+                        } else {
+                            work.data++;
+                        }
+                    }
+                }
+                if (data.bitlength <= work.bitcount) {
+                    work.state = Trailer;
+                }
+            } else if (data.format == RemoteIR::AEHA) {
+                /*
+                 * AEHA.
+                 */
+                if (work.data == 0) {
+                    tx.write(0.5);
+                    work.data++;
+                } else {
+                    tx.write(0.0);
+                    if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
+                        if (3 <= work.data) {
+                            work.bitcount++;
+                            work.data = 0;
+                        } else {
+                            work.data++;
+                        }
+                    } else {
+                        if (1 <= work.data) {
+                            work.bitcount++;
+                            work.data = 0;
+                        } else {
+                            work.data++;
+                        }
+                    }
+                }
+                if (data.bitlength <= work.bitcount) {
+                    work.state = Trailer;
+                }
+            } else if (data.format == RemoteIR::SONY) {
+                /*
+                 * SONY.
+                 */
+                if (work.data == 0) {
+                    tx.write(0.0);
+                    work.data++;
+                } else {
+                    tx.write(0.5);
+                    if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
+                        if (2 <= work.data) {
+                            work.bitcount++;
+                            work.data = 0;
+                        } else {
+                            work.data++;
+                        }
+                    } else {
+                        if (1 <= work.data) {
+                            work.bitcount++;
+                            work.data = 0;
+                        } else {
+                            work.data++;
+                        }
+                    }
+                }
+                if (data.bitlength <= work.bitcount) {
+                    work.state = Trailer;
+                }
+            } else {
+            }
+            break;
+        case Trailer:
+            if (data.format == RemoteIR::NEC) {
+                /*
+                 * NEC.
+                 */
+                static const int TRAILER_NEC_HEAD = 1;
+                static const int TRAILER_NEC_TAIL = 2;
+                if (work.trailer < TRAILER_NEC_HEAD) {
+                    tx.write(0.5);
+                } else {
+                    tx.write(0.0);
+                }
+                work.trailer++;
+                if ((TRAILER_NEC_HEAD + TRAILER_NEC_TAIL) <= work.trailer) {
+                    work.state = Idle;
+                    //ticker.detach();
+                }
+            } else if (data.format == RemoteIR::AEHA) {
+                /*
+                 * AEHA.
+                 */
+                static const int TRAILER_AEHA_HEAD = 1;
+                static const int TRAILER_AEHA_TAIL = 8000 / RemoteIR::TUS_AEHA;
+                if (work.trailer < TRAILER_AEHA_HEAD) {
+                    tx.write(0.5);
+                } else {
+                    tx.write(0.0);
+                }
+                work.trailer++;
+                if ((TRAILER_AEHA_HEAD + TRAILER_AEHA_TAIL) <= work.trailer) {
+                    work.state = Idle;
+                    //ticker.detach();
+                }
+            } else if (data.format == RemoteIR::SONY) {
+                /*
+                 * SONY.
+                 */
+                static const int TRAILER_SONY_HEAD = 0;
+                static const int TRAILER_SONY_TAIL = 0;
+                if (work.trailer < TRAILER_SONY_HEAD) {
+                    tx.write(0.5);
+                } else {
+                    tx.write(0.0);
+                }
+                work.trailer++;
+                if ((TRAILER_SONY_HEAD + TRAILER_SONY_TAIL) <= work.trailer) {
+                    work.state = Idle;
+                    //ticker.detach();
+                }
+            } else {
+            }
+            break;
+        default:
+            break;
+    }
+    UNLOCK();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Propo_RemotoIR/TransmitterIR.h	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,83 @@
+/**
+ * IR transmitter (Version 0.0.4)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#ifndef _TRANSMITTER_IR_H_
+#define _TRANSMITTER_IR_H_
+
+#include <mbed.h>
+
+#include "RemoteIR.h"
+
+/**
+ * IR transmitter class.
+ */
+class TransmitterIR {
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param txpin Pin for transmit IR signal.
+     */
+    explicit TransmitterIR(PinName txpin);
+
+    /**
+     * Destructor.
+     */
+    ~TransmitterIR();
+
+    typedef enum {
+        Idle,
+        Leader,
+        Data,
+        Trailer
+    } State;
+
+    /**
+     * Get state.
+     *
+     * @return Current state.
+     */
+    State getState(void);
+
+    /**
+     * Set data.
+     *
+     * @param format Format.
+     * @param buf Buffer of a data.
+     * @param bitlength Bit length of the data.
+     *
+     * @return Data bit length.
+     */
+    int setData(RemoteIR::Format format, uint8_t *buf, int bitlength);
+
+private:
+
+    typedef struct {
+        State state;
+        int bitcount;
+        int leader;
+        int data;
+        int trailer;
+    } work_t;
+
+    typedef struct {
+        RemoteIR::Format format;
+        int bitlength;
+        uint8_t buffer[64];
+    } data_t;
+
+    PwmOut tx;
+    Ticker ticker;
+    data_t data;
+    work_t work;
+
+    void tick();
+
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,189 @@
+/**
+ * HonyBee Propo Decode test program 
+ *   130623
+ *
+ * Writer:suupen
+ *
+ *  <circuit diagram>
+ *      VU(mbed)
+ *         |
+ *         |Vcc
+ *        ---    (PL-IRM2161) IR Reciver
+ *       |   |Vout
+ *       |   |--- p5(mbed)
+ *       |   |
+ *        ---
+ *         |GND
+ *         |
+ *       GND(mbed)
+ *
+ *  <PC termnal soft>
+ *   tera term
+ *      baudrate:38400[bps]
+ *      data:8[bit]
+ *      parity:none
+ *      stopbit:1[bit]
+ */
+
+ 
+//#define PROPO_RAW_DATA        // ari: zyusin data hyoji   nasi:HonyBee kaiseki data hyoji
+//#define HONYBEE_NORMALIZE     // ari: HonyBee data seikika hyoji  nasi: HonyBee data tujyo hyoji
+ 
+#include "mbed.h"
+#include "ReceiverIR.h"
+
+#ifndef PROPO_RAW_DATA
+#include "CodecHonyBee.h"
+#include "DecodeHonyBee.h"
+#endif // PROPO_RAW_DATA
+
+void display_format(RemoteIR::Format format);
+void display_binary(uint8_t *buf, uint8_t cnt);
+
+Serial pc(USBTX,USBRX);
+
+
+ReceiverIR ir_rx(p5);
+
+RemoteIR::Format format;
+
+#ifndef PROPO_RAW_DATA
+DecodeHonyBee HonyBee;
+CodecHonyBee::honyBeePropo_t HonyBeeData;
+
+#ifdef HONYBEE_NORMALIZE
+CodecHonyBee::normalizePropo_t normalize;
+#endif // HONYBEE_NORMALIZE
+
+#endif // PROPO_RAW_DATA
+
+
+uint8_t buf[32];
+int bitcount;
+
+DigitalOut myled(LED1);
+DigitalOut led2(LED2);
+DigitalIn irtest(p20);
+
+
+int main(){
+    pc.baud(38400);
+    while(1){
+
+    myled =~myled;
+    led2 = irtest;
+
+
+ 
+ #ifdef PROPO_RAW_DATA
+    if (ir_rx.getState() == ReceiverIR::Received) {
+        bitcount = ir_rx.getData(&format, buf, sizeof(buf) * 8);
+        
+        display_format(format);
+        display_binary(buf, ((bitcount + 7) / 8));
+     }
+    else{
+#if 0
+        switch(ir_rx.getState()){
+        
+        case ReceiverIR::Idle:
+            printf("Idele\n");
+            break;
+        case ReceiverIR::Receiving:
+            printf("Receiveing\n");
+            break;
+        case ReceiverIR::Received:
+            printf("Received\n");
+        break;
+        }
+#endif
+    }
+#endif // PROPO_RAW_DATA
+
+#ifndef PROPO_RAW_DATA
+     if (ir_rx.getState() == ReceiverIR::Received) {
+        bitcount = ir_rx.getData(&format, buf, sizeof(buf) * 8);
+#ifdef HONYBEE_NORMALIZE
+        bool ans = HonyBee.normalize(buf, &normalize);
+        if(ans == true){
+            printf("count = %02x band = %1d  slottle = %f trim = %f ladder = %f elevator = %f\n",normalize.count,normalize.band,normalize.slottle,normalize.trim,normalize.ladder, normalize.elevator);
+       }
+        else{
+            printf("NG\n");
+        }        
+#else // ~HONYBEE_NORMALIZE
+        bool ans = HonyBee.decode(buf, &HonyBeeData);
+        if(ans == true){
+            printf("count = %02x band = %02x  slottle = %03d trim = %03d ladder = %03d \n",HonyBeeData.count,HonyBeeData.band,HonyBeeData.slottle,HonyBeeData.trim,HonyBeeData.ladder);
+       }
+        else{
+            printf("NG\n");
+        }
+#endif// HONYBEE_NORMALIZE
+
+     }
+#endif // PROPO_RAW_DATA
+
+    }
+ 
+}
+
+/**
+ * Display a format of a data.
+ */
+void display_format(RemoteIR::Format format) {
+    switch (format) {
+        case RemoteIR::UNKNOWN:
+            pc.printf("????????");
+            break;
+        case RemoteIR::NEC:
+            pc.printf("NEC     ");
+            break;
+        case RemoteIR::NEC_REPEAT:
+            pc.printf("NEC  (R)");
+            break;
+        case RemoteIR::AEHA:
+            pc.printf("AEHA    ");
+            break;
+        case RemoteIR::AEHA_REPEAT:
+            pc.printf("AEHA (R)");
+            break;
+        case RemoteIR::SONY: //HONEY_BEE:
+            pc.printf("SONY or HONEY_BEE    ");
+            break;
+
+#ifdef Swift_PROTCOL
+        case RemoteIR::Swift:
+            pc.printf("Swift   ");
+            break;
+#endif // Swift_PROPO
+        default:
+            pc.printf("unknown  ");
+            break;
+    }
+}
+
+void display_binary(uint8_t *buf, uint8_t cnt){
+    uint8_t i;
+    uint8_t bitcnt;
+    uint8_t dat;
+    uint16_t checkbit;
+    
+    for(i = 0; i < cnt; i++){
+        checkbit = 0x0080;
+        dat = *(buf + i);
+        printf("%02x:",dat);
+        for(bitcnt = 0; bitcnt < 8; bitcnt++){
+            if( checkbit & dat){printf("1");}
+            else {printf("0");}
+            
+            checkbit = checkbit >> 1;
+            if(bitcnt == 3){printf(" ");}
+        }
+        printf("  ");
+    }
+    printf("\n");
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Jun 23 07:28:06 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/b3110cd2dd17
\ No newline at end of file