RN41/42 control lib. RN41/42 is bluetooth module with class 1 or 2.
Dependencies: StrLib myTimer RingBuffer
Diff: RN41.cpp
- 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