RN41/42 control lib. RN41/42 is bluetooth module with class 1 or 2.

Dependencies:   StrLib myTimer RingBuffer

Dependents:   Theremin

Revision:
0:812e6b59aa54
Child:
1:5ed110051e39
diff -r 000000000000 -r 812e6b59aa54 RN41.cpp
--- /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