Akinori Hashimoto / RN41

Dependencies:   StrLib myTimer RingBuffer

Dependents:   Theremin

Files at this revision

API Documentation at this revision

Comitter:
AkinoriHashimoto
Date:
Tue Oct 20 01:32:17 2015 +0000
Child:
1:5ed110051e39
Commit message:
beta publish.

Changed in this revision

RN41.cpp Show annotated file Show diff for this revision Revisions of this file
RN41.h Show annotated file Show diff for this revision Revisions of this file
StrLib.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RN41.cpp	Tue Oct 20 01:32:17 2015 +0000
@@ -0,0 +1,339 @@
+#include "RN41.h"
+//#include "SerialBase.h"
+
+//extern void sendHC05(string);
+
+
+
+const int RN41::NG=                   0;
+const int RN41::OK=                   1;
+
+// PRIVATE
+const int RN41::findCmp12=          100;
+const int RN41::findCmp1=           101;
+const int RN41::findCmp2=           102;
+
+// PUBLIC
+const int RN41::ERR_AddrUnder12=    210;
+const int RN41::ERR_AddrOver12=     211;
+const int RN41::ERR_Connect=        220;
+const int RN41::FAIL_Connect=       221;
+const int RN41::ERR_EnterCmdMode=   230;
+const int RN41::ERR_Disconnect=     240;
+
+const int RN41::ERR_NameSize=       310;
+
+/*
+const int RN41::None=                10;
+const int RN41::Odd=                 11;
+const int RN41::Even=                12;
+*/
+
+
+
+RN41::RN41(PinName TX, PinName RX, int baudrate, int bit, int parity, int stop, bool CRLN)
+    : rn41(TX, RX)
+{
+    rn41.baud(baudrate);
+    /*
+        Parity _parity= SerialBase::None;      // enum
+        if(parity == 'O')
+            _parity= SerialBase::Odd;
+        if(parity == 'E')
+            _parity= SerialBase::Even;
+        rn41.format(bit, _parity, stop);     // 8bit, NonParity, 1stopbit
+    */
+
+    // 力技
+    if      (parity == SerialBase::Odd)
+        rn41.format(bit, SerialBase::Odd,  stop);
+    else if (parity == SerialBase::Even)
+        rn41.format(bit, SerialBase::Even, stop);     // 8bit, NonParity, 1stopbit
+    else// if (parity == SerialBase::None)
+        rn41.format(bit, SerialBase::None, stop);     // 8bit, NonParity, 1stopbit
+
+    CR= '\r';
+    if(CRLN)
+        CR= "\r\n";
+}
+
+
+int RN41::connect(string addr)
+{
+    timerLocal.reset();
+    timerLocal.start();
+
+    addr= toAlpanumeric(addr, true);
+    int idx= addr.size();
+    // ex. 0006:66:72:6e05\r ->000666726e05.
+    if(idx < 12)
+        return ERR_AddrUnder12;
+    if(idx > 12)
+        return ERR_AddrOver12;
+
+    if(!enterCMD())
+        return ERR_EnterCmdMode;       // CMD入れず
+//    sendHC05("test 100");
+    if(!disconnect())
+        return ERR_Disconnect;
+    if(!enterCMD())
+        return ERR_EnterCmdMode;       // CMD入れず
+
+    // BT addr check success;
+    sendCMD("C,"+ addr);
+    int status;
+
+//    wait(1.0);read();sendHC05("--"+ rxStr+ "**");
+
+    status= chkReply("TRYING\r", 1000, "ERR\r");
+    if(status == findCmp2)
+        return ERR_Connect;
+    else if(status == findCmp1) {
+        // Trying to connect to remote Bluetooth dev.
+
+//        wait(7.0);        read();        sendHC05(rxStr);
+        timerLocal.reset();
+        timerLocal.start();
+        status= chkReply("CONNECT,", 10000, "CONNECT failed\r");    // wait 10s
+
+//        sendHC05("Time of Create-Connection: "+ I2A(timerLocal.read_ms())+ " ms.");
+
+        if(status == findCmp1)
+            return OK;
+        else if(status == findCmp2)
+            return FAIL_Connect;
+    } else {
+//        sendHC05("connect:"+ I2A(status));
+    }
+    return 1234;
+}
+
+
+
+
+string RN41::getLine()
+{
+    read();
+    // CRまでを返す
+
+//sendHC05("debug 10");
+    if(str4GetLine.size()==0 && rxStr.size()==0)
+        return "";
+
+// trying->Connect待ちをTickerにすると、そこんとの除外処理が必須。
+//    sendHC05("debug 20");
+
+    // rxStr.size() > 0
+    int idx= rxStr.rfind(CR);
+//    sendHC05("rxStr: "+ rxStr);    sendHC05("idxCR: "+ I2A(idx));
+    if(idx == string::npos)     // not find CR!
+        return str4GetLine;     // ダメじゃね??
+
+//    sendHC05("debug 30");
+    // rxStr has CR.
+    idx += CR.size();   // \rなら+1、\r\nは+2
+    string rtn= str4GetLine;
+    rtn += rxStr.substr(0, idx);   // 切り取り
+    rxStr= rxStr.substr(idx);
+//    sendHC05("debug 40");
+    return rtn;
+}
+
+
+
+int RN41::setDev_Name(string str, bool usingAddr)
+{
+    int strSize= str.size();
+    if((strSize==0) || (20<=strSize) || (usingAddr && 15<=strSize))
+        return ERR_NameSize;
+
+    // 特殊文字チェックは不要っぽい
+
+    string cmd;
+    if(usingAddr)
+        cmd= "S-,";
+    else
+        cmd= "SN,";
+
+    if(!enterCMD())
+        return ERR_EnterCmdMode;       // CMD入れず
+
+
+    sendCMD(cmd+ str);
+    int status;
+//    wait(1.0);read();sendHC05("--"+ rxStr+ "**");
+    status= chkReply("AOK\r", 1000);
+    if(status == findCmp1)
+        return OK;
+
+    return NG;
+}
+
+
+void RN41::sendCMD(string str, bool addCR)
+{
+    if(addCR)
+        str += '\r';
+    rn41.printf(str.c_str());
+    return;
+}
+void RN41::sendLINE(string str, bool addCR)
+{
+    if(addCR)
+        str += "\r\n";
+    rn41.printf(str.c_str());
+    return;
+}
+
+
+
+bool RN41::enterCMD()
+{
+    sendCMD("$$$", false);
+    if(chkReply("CMD\r", 500) == findCmp1) {    // 500ms
+//        sendHC05("returned CMD.");
+        return true;
+    }
+
+    sendCMD("\r", false);           // 既にCMDモード
+    if(chkReply("?\r", 500) == findCmp1) {
+//        sendHC05("Already CmdMode.");
+        return true;
+    }
+    return false;
+}
+
+
+
+bool RN41::disconnect()
+{
+    //    if(!enterCMD())        return false;       // CMD入れず
+
+    sendCMD("K,");     // rtn KILL ? / ERR ?
+    int status;
+//    wait(6.0);    read();    sendHC05("in disconnect; \t"+ rxStr);
+
+    status= chkReply("KILL\r", 500, "ERR\r");
+    if(status == findCmp2) {    // 既に切断されている
+        sendCMD("---");        // exit CMD mode.
+        if(chkReply("END\r", 500) == findCmp1)
+            return true;
+        else// {            leds.ON(4);
+            return false;   // どういう状況か不明
+    } else if(status == findCmp1) {
+//        if(chkReply("DISCONNECT", 2000) == findCmp1)
+        if(chkReply_woCR("DISCONNECT", 5000))  // CR無いかも?
+            return true;
+        else //{            leds.ON(3);
+            return false;   // どういう状況か不明
+    }// else {        return false;    }
+    return false;
+}
+
+
+
+
+int RN41::chkReply(string cmp1, int timeout, string cmp2)
+{
+    timerLocal.reset();
+    timerLocal.start();
+
+    int cmp2Size= cmp2.size();
+    int idxCR, idx1, idx2;//= string::npos;
+    bool find1, find2;
+    for(;;) {
+        if(timerLocal.read_ms() > timeout)
+            return NG;
+
+        read();
+        idxCR= rxStr.find_first_of('\r');
+        if(idxCR != string::npos) {     // CR found.
+            idx1= idx2= string::npos;   // -1
+            find1= find2= false;
+            idx1= rxStr.find(cmp1);
+            if(cmp2Size != 0)
+                idx2= rxStr.find(cmp2);
+
+            // idx1: 0< or npos, idx2: 0< or npos(notfined or size0)
+            int idxCut;
+            //idx1(~CR) -> idx2(~CR)
+            if(idx1 != string::npos)
+                if(idx1 < idxCR)
+                    find1= true;
+            if(idx2 != string::npos)
+                if(idx2 < idxCR)
+                    find2= true;
+
+//sendHC05("++"+ rxStr+ "**");
+//sendHC05("idx1:"+cmp1+":"+ I2A(idx1)+ "\tidx2:"+cmp2+":"+ I2A(idx2)+ "\tidxCR:"+ I2A(idxCR));
+
+            // CRまで切り取り。findならば切り捨て、見つからなければコピー後切り捨て
+            idxCut= idxCR+ 1;
+            if(rxStr[idxCut] == '\n')
+                idxCut++;
+            // 切り捨てはidxからの切り取りを上書き。コピーは文字数なので、idxが-1まで。
+            if(!(find1 || find2))
+                str4GetLine= rxStr.substr(0, idxCut);
+            rxStr= rxStr.substr(idxCut);        // 切り取りは共通。
+
+            if(find1 && find2)     // find1有、find2有
+                return findCmp12;
+            if(find1)
+                return findCmp1;
+            if(find2)
+                return findCmp2;
+            // CR内にCMP無い場合は、ループへ
+        }
+    }   // end for
+}
+
+
+bool RN41::chkReply_woCR(string cmp, int timeout)
+{
+    timerLocal.reset();
+    timerLocal.start();
+
+    int idx;
+    for(;;) {
+        if(timerLocal.read_ms() > timeout) {
+//            sendHC05("in chkReply; "+ rxStr);
+            return false;
+        }
+        read();
+        idx= rxStr.find(cmp);
+        if(idx != string::npos) {
+            // めんどいから消去する。
+            idx= rxStr.find_first_of('\r');
+            if(idx == string::npos)
+                rxStr= "";
+            else {
+                idx++;
+                if(rxStr[idx] == '\n')
+                    idx++;
+                rxStr= rxStr.substr(idx);
+            }
+//            rxStr= "";
+            return true;
+        }
+    }
+}
+
+
+
+
+void RN41::read()
+{
+    if(!rn41.readable())
+        return;
+
+    // Bufferを吸い尽くす
+//    char ch;
+    for(;;) {
+//        char ch= rn41.getc();    // 1文字取る
+//        ch= rn41.getc();    // 1文字取る
+//        rxStr += ch;            // 上書き前に退避
+        rxStr += (char)rn41.getc();
+        if(!rn41.readable())
+            return; //break;    // Bufferになくなった
+    } // end for
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RN41.h	Tue Oct 20 01:32:17 2015 +0000
@@ -0,0 +1,86 @@
+/**     RN41/42 is Bluetooth module. RN41 is calss 1, RN42 is class 2.
+ *  RN42 refer to http://akizukidenshi.com/catalog/g/gM-07612/ .
+ */
+
+#pragma once
+
+#include "mbed.h"
+#include "StrLib.h"
+
+/*
+ * cmdで送る改行コードは、CRのみ。LFは文字として認識されるので?となる。
+ * RN41 Returns (default); AOK(valid cmd), ERR(invalid cmod), ?(unrecongnized cmd).
+
+%を付ける初期化処理必須
+
+*/
+
+
+/**     Bluetooth module RN41/42 control class.
+ *
+ */
+class RN41
+{
+public:
+
+//    static const int
+    static const int NG, OK;//=                  1;
+    static const int ERR_AddrUnder12, ERR_AddrOver12, ERR_Connect, FAIL_Connect;
+    static const int ERR_EnterCmdMode, ERR_Disconnect;
+
+//    static const int None, Odd, Even;
+    static const int ERR_NameSize;
+
+    /** Create Serial port to RN41. for LPC1768
+     *  @param TX, RX;              Serial port.
+     *  @param baud-rate;                Baud rate (bps).
+     *  @param bit, parity, stop;   Default: 1Stopbit, NoneParity, 1StopBit.
+     *                              -- parity select; N(None), O(Odd), E(Even).
+     *  @param CRLN;                true -> CR&LN (\r\n), false -> CR only (\r).
+     */
+    RN41(PinName TX, PinName RX, int baudrate, int bit=8, int parity=SerialBase::None, int stop=1, bool CRLN=true);
+
+    /**
+     *      RxStrのCRまでを返す。
+     */
+    string getLine();
+
+    /**
+     *
+     */
+    void sendCMD( string str, bool addCR=true);
+    void sendLINE(string str, bool addCR=true);
+
+
+    int setDev_Name(string str, bool usingAddr=true);
+    int setDev_UART(int boad, int stop=1, int parity=SerialBase::None);
+
+
+// Command to RN41
+    bool enterCMD();
+    int connect(string addr);     // 必ず、Checkを呼ぶこと。2-5sかかるよ
+    bool disconnect();
+
+private:
+    Serial rn41;
+    string CR;
+    string rxStr, str4GetLine;      // 内部バッファ。read()での保管用と、GetLineまでの保管用。
+
+    Timer timerLocal;
+
+    static const int findCmp1, findCmp2, findCmp12;
+    /** check reply from RN41.
+     *  @Param  cmp; string to compare
+     *  @Param  timeout; timeout [ms]
+     *  @return bool; true: ok, false: NG.
+     */
+    int chkReply(string cmp1, int timeout, string cmp2="");
+
+    bool chkReply_woCR(string cmp, int timeout);
+
+    /** Just copy to rxStr from Buffer.
+    *
+    */
+    void read();
+
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StrLib.lib	Tue Oct 20 01:32:17 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/AkinoriHashimoto/code/StrLib/#7bc89a64bfbd