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

Dependencies:   StrLib myTimer RingBuffer

Dependents:   Theremin

Revision:
2:3a28bc9332b6
Parent:
1:5ed110051e39
Child:
3:2a87c102ddd3
--- a/RN41.cpp	Thu Oct 22 05:02:36 2015 +0000
+++ b/RN41.cpp	Wed Oct 28 04:49:41 2015 +0000
@@ -32,6 +32,10 @@
     : rn41(TX, RX)
 {
     this->setDev_UART(baudrate, bit, parity, stop);
+
+    // attach rxIrq. because, rx buf of serial equals to 16 Bytes.
+    this->rn41.attach(this, &RN41::_readIrq, Serial::RxIrq);
+
     cr= '\r';
     if(CRLN)
         cr= "\r\n";
@@ -55,44 +59,56 @@
         return ERR_EnterCmdMode;       // CMD入れず
 
     sendCMD("C,"+ addr);
-    int status;
+    bool2 find;
+    find= chkReply("TRYING\r", 1000, "ERR\r");    // within waiting for Reply
 
-    status= chkReply("TRYING\r", 1000, "ERR\r");    // within waiting for Reply
-
-    if(status == findCmp2)
+    // TRYINGが返って来ない場合
+    if(!find.b1)
         return ERR_Connect;
-    else if(status == findCmp1) {
-        // Trying to connect to remote Bluetooth dev.
-        status= chkReply("CONNECT,", 10000, "CONNECT failed\r");    // wait 10s(max)
-        if(status == findCmp1)
-            return OK;
-        else if(status == findCmp2)
-            return FAIL_Connect;
-        else if(status == ERR_Timeout)
-            return ERR_Timeout;
-    }
-    return 1234;
+
+    // Trying to connect to remote Bluetooth dev.
+    find= chkReply("CONNECT,", 10000, "CONNECT failed\r");    // wait 10s(max)
+
+    if(find.b1)
+        return OK;
+    if(find.b2)
+        return FAIL_Connect;
+
+    return ERR_Timeout;
 }
 
+string RN41::read()
+{
+    _read();
+    if(rxStrStored.empty() && rxStr.empty())
+        return "";
+
+    string tmp= rxStrStored+ rxStr;
+    rxStr.erase();
+    rxStrStored.erase();
+    return tmp;
+}
 
 string RN41::getLine()
 {
-    read();
+    _read();
     // CRまでを返す
 
-    if(str4GetLine.size()==0 && rxStr.size()==0)
+    if(rxStrStored.empty() && rxStr.empty())
         return "";
 
-    int idx= rxStr.rfind(cr);
-    if(idx == string::npos)     // not find CR!
-        return str4GetLine;     // ダメじゃね??
+    int idx= rxStr.rfind('\r');
+    if(idx != string::npos) {       // CR存在
+        if(rxStr[++idx] == '\n')
+            idx++;
+        rxStrStored += rxStr.substr(0, idx);  // size
+        rxStr= rxStr.substr(idx);             // idx
+    }
+    // rxStrはCRなし、rxStrStoredに調整済み
 
-    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;
+    string tmp= rxStrStored;
+    rxStrStored.erase();
+    return tmp;
 }
 
 
@@ -110,6 +126,10 @@
     else
         return NG;
 
+    // 9,600bps -> 1,200B/s -> 833us/B. 0.1文字×13回待ちする(安全率30%)。
+//    usWait4readBuf= (int)( (float)800000 / (float)baud );
+//    if(usWait4readBuf < 1)usWait4readBuf= 1;
+
     return OK;
 }
 
@@ -132,9 +152,7 @@
         return ERR_EnterCmdMode;       // CMD入れず
 
     sendCMD(cmd+ str);
-    int status;
-    status= chkReply("AOK\r", 1000);
-    if(status == findCmp1)
+    if(chkReply("AOK\r", 1000).b1)
         return OK;
 
     return NG;
@@ -156,84 +174,178 @@
     return;
 }
 
-
-
 bool RN41::enterCMD()
 {
     sendCMD("$$$", false);
-    if(chkReply("CMD\r", 500) == findCmp1)    // 500ms
+    if(chkReply("CMD\r", 500).b1)    // 500ms
         return true;
 
-
     sendCMD("\r", false);           // 既にCMDモード
-    if(chkReply("?\r", 500) == findCmp1)
+    if(chkReply("?\r", 500).b1)
         return true;
+        
     return false;
 }
 
-
-
 bool RN41::disconnect()
 {
     if(!enterCMD())
         return false;       // CMD入れず
     sendCMD("K,");     // rtn KILL ? / ERR ?
-    int status;
 
-    status= chkReply("KILL\r", 500, "ERR\r");
-    if(status == findCmp2) {    // 既に切断されている
+    bool2 find;
+    find= chkReply("KILL\r", 500, "ERR\r");
+    if(find.b2) {    // 既に切断されている
         sendCMD("---");        // exit CMD mode.
-        if(chkReply("END\r", 500) == findCmp1)
-            return true;
-        else// {            leds.ON(4);
-            return false;   // どういう状況か不明
-    } else if(status == findCmp1) {
-        if(chkReply_woCR("DISCONNECT", 5000))  // CR無いかも?
-            return true;
-        else
-            return false;   // どういう状況か不明
+        return chkReply("END\r", 500).b1;
+//            return true;else// {            leds.ON(4);return false;   // どういう状況か不明
     }
-    return false;
+    // 切断中
+    return chkReply("DISCONNECT", 5000, "", false).b1;  // CR無いかも?
 }
 
+
+RN41::bool2 RN41::chkReply(string cmp1, int timeout, string cmp2, bool wCR) // withCR
+{
+    // BT外側から文字列が到着しないと仮定。
+    // 目的単語は、取り逃していないと仮定。
+
+    if(rxStr[0] == '\n')
+        rxStr= rxStr.substr(1);
+
+    timer.start(true);      // for Timeout
+    int idxCR;//, idx1, idx2;//, idxCut;
+//    bool2 find;//1, find2;
+    bool2 find, tmpFind;
+    string tmpStr;
+
+
+    find.b1= find.b2= false;    // rxStr全てを確認するために、trueのみ上書きしていく。
+    while(true) {
+        _read();
+        // rxStrを確認する。
+
+        idxCR= rxStr.find('\r');
+        if(idxCR != string::npos) {     // CR found.
+            // 通常通信、目的語(wCR)、目的語(woCR)+通常通信。の3パターンのみのはず。
+
+            // tmpに切り取って確認する。
+            idxCR++;
+            if(rxStr[idxCR] == '\n')
+                idxCR++;
+            // rxStr[idxCR]は次の文字列のidx
+            tmpStr= rxStr.substr(0, idxCR); // substr(idx, count)
+            rxStr=  rxStr.substr(idxCR);
+
+            tmpFind= chkReply_line(tmpStr, cmp1, cmp2);
+            if(tmpFind.b1)
+                find.b1= true;
+            if(tmpFind.b2)
+                find.b2= true;
+            if(!(tmpFind.b1 || tmpFind.b2))     // 通常通信
+                rxStrStored += tmpStr;
+        } else {
+            // CRなし
+            tmpFind= chkReply_line(rxStr, cmp1, cmp2);
+            // この時点で、tmpとfindの両方がTrueの場合、目的のリプが2回出てきた。おかしい。
+            // とりあ、そのケースは無視。
+            if(tmpFind.b1)
+                find.b1= true;
+            if(tmpFind.b2)
+                find.b2= true;
+
+            bool flagRtn= false;
+            if(find.b1||find.b2)
+                flagRtn= true;
+
+            // Return準備
+            if( wCR && (tmpFind.b1||tmpFind.b2))
+                flagRtn= false;
+
+            if(!wCR && (tmpFind.b1||tmpFind.b2)) {
+                int idx1, idx2;
+                idx1= rxStr.find(cmp1);
+                if(!cmp2.empty())
+                    idx2= rxStr.find(cmp2);
+                else
+                    idx2= string::npos;
+
+                if(idx1 != string::npos)
+                    idx1 += cmp1.size();
+                else
+                    idx1= 0;
+                if(idx2 != string::npos)
+                    idx2 += cmp2.size();
+                else
+                    idx2= 0;
+
+                if(idx1 < idx2)
+                    idx1= idx2;
+                rxStr= rxStr.substr(idx1);
+            }
+
+            if(flagRtn)
+                return find;
+        }
+
+        if(timer.read_ms(false, false, false) > timeout)
+            return find;
+        wait_ms(2);     // 1ms waiting.
+    }   // end while
+}
+
+RN41::bool2 RN41::chkReply_line(string trg, string cmp1, string cmp2)   //, bool wCR) // withCR
+{
+    bool2 tmp;
+    tmp.b1= tmp.b2= false;
+
+    if(    trg.find(cmp1) != string::npos)
+        tmp.b1= true;
+    if(!cmp2.empty())
+        if(trg.find(cmp2) != string::npos)
+            tmp.b2= true;
+
+    return tmp;
+}
+
+
+/*
 int RN41::chkReply(string cmp1, int timeout, string cmp2)
 {
-    timer.start(true);
+//    _read();//    rxStrStored += rxStr;
 
-    int cmp2Size= cmp2.size();
-    int idxCR, idx1, idx2;
+    timer.start(true);
+//    int cmp2Size= cmp2.size();
+    int idxCR, idx;//1, idx2;//, idxCut;
     bool find1, find2;
 
     // RxStrのチェック必要じゃね?初期化とか
-    int idxCut;
     while(true) {
-        if(timer.read_ms(false, false, false) > timeout)
-            return ERR_Timeout;
-        read();
+        _read();
         idxCR= rxStr.find('\r');
         if(idxCR != string::npos) {     // CR found.
-
+            // 最初のCRまでを確認。
             find1= find2= false;
             // idx1: 0< or npos, idx2: 0< or npos(notfined or size0)
             //idx1(~CR) -> idx2(~CR)
-            idx1= rxStr.find(cmp1);
-            if((idx1 != string::npos) && (idx1 < idxCR))
+            idx= rxStr.find(cmp1);
+            if((idx != string::npos) && (idx < idxCR))
                 find1= true;
 
-            if(cmp2Size != 0) {
-                idx2= rxStr.find(cmp2);
-                if((idx2 != string::npos) && (idx2 < idxCR))
+            if(!cmp2.empty()) { //(cmp2.size() != 0) {
+                idx= rxStr.find(cmp2);
+                if((idx != string::npos) && (idx < idxCR))
                     find2= true;
             }
 
-            // CRまで切り取り。findならば切り捨て、見つからなければコピー後切り捨て
-            idxCut= idxCR+ 1;
-            if(rxStr[idxCut] == '\n')
-                idxCut++;
-            // 切り捨てはidxからの切り取りを上書き。コピーは文字数なので、idxが-1まで。
+            // CRまで切り取り。findならば削除。見つからなければ目的でない、通常通信とみなし、コピー。
+            idxCR++;//idxCut= idxCR+ 1;
+            if(rxStr[idxCR] == '\n')
+                idxCR++;
+            // 切り捨てはidxからの切り取りを上書き。コピーは文字数。
             if(!(find1 || find2))
-                str4GetLine= rxStr.substr(0, idxCut);
-            rxStr= rxStr.substr(idxCut);        // 切り取りは共通。
+                rxStrStored += rxStr.substr(0, idxCR);
+            rxStr= rxStr.substr(idxCR);        // 切り取りは共通。
 
             if(find1 && find2)     // find1有、find2有
                 return findCmp12;
@@ -243,54 +355,78 @@
                 return findCmp2;
             // CR内にCMP無い場合は、ループへ
         }   // (idxCR != string::npos)
+
+        if(timer.read_ms(false, false, false) > timeout)
+            return ERR_Timeout;
         wait_ms(2);     // 1ms waiting.
     }   // end for
 }
-
-
 bool RN41::chkReply_woCR(string cmp, int timeout)
 {
-    timer.start(true);
+//    _read();rxStrStored += rxStr;
 
-    int idx;
+    timer.start(true);
+    int idx, idxCR;
     while(true) {
-        if(timer.read_ms(false, false, false) > timeout)
-            return false;
-
-        read();
+        _read();
         idx= rxStr.find(cmp);
-        
+
         if(idx != string::npos) {
-            idx= rxStr.find('\r');
-            // find CRLF
-            if(idx == string::npos)
-                rxStr= "";
-            else {
-                idx++;
-                if(rxStr[idx] == '\n')
-                    idx++;
+            idxCR= rxStr.find('\r');
+
+            if(idxCR == string::npos)
+                rxStr.erase();      // 目的の単語のみと判断する。使用済みなので消去。
+            else {      // CR存在するので、目的単語の前後で意図が異なる。
+                idxCR++;
+                if(rxStr[idxCR] == '\n')
+                    idxCR++;
+                // CR後の最初の文字位置
+
                 rxStr= rxStr.substr(idx);
             }
             return true;
         }
+
+        if(timer.read_ms(false, false, false) > timeout)
+            return false;
         wait_ms(2);
     }
 }
-
-
+*/
 
 
-void RN41::read()
+void RN41::_readIrq(void)
 {
-    if(!rn41.readable())
-        return;
-
+    if(rn41.readable())
+        rxStr += (char)rn41.getc();
+    return;
+}
+void RN41::_read()
+{
     // Bufferを吸い尽くす
-    while(true) {
+    while(rn41.readable())
         rxStr += (char)rn41.getc();
-        if(!rn41.readable())
-            return;         // Bufferになくなった
-    } // end for
+
+    return;         // Bufferになくなった
 }
+/*
+void RN41::_read()
+{
+    // Bufferを吸い尽くす
+    // bps(Baudrate)から一文字分待ち、それでも受信がなければBuf空と判断。
+    int iter= 0;
+    while(true) {
+        if(rn41.readable()) {
+            rxStr += (char)rn41.getc();
+            iter= 0;    //reset
+        } else {
+            wait_us(usWait4readBuf);
+            iter++;
+            if(iter > 13)   // 安全率30%
+                return;         // Bufferになくなった
+        }
+    } // end while
+}
+*/
 
 // EOF
\ No newline at end of file