RN41/42 control lib. RN41/42 is bluetooth module with class 1 or 2.
Dependencies: StrLib myTimer RingBuffer
RN41.cpp
- Committer:
- AkinoriHashimoto
- Date:
- 2015-10-28
- Revision:
- 2:3a28bc9332b6
- Parent:
- 1:5ed110051e39
- Child:
- 3:2a87c102ddd3
File content as of revision 2:3a28bc9332b6:
#include "RN41.h" //#include "SerialBase.h" 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_Timeout= 201; 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) { 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"; } int RN41::connect(string addr) { 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入れず if(!disconnect()) return ERR_Disconnect; if(!enterCMD()) return ERR_EnterCmdMode; // CMD入れず sendCMD("C,"+ addr); bool2 find; find= chkReply("TRYING\r", 1000, "ERR\r"); // within waiting for Reply // TRYINGが返って来ない場合 if(!find.b1) return ERR_Connect; // 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(); // CRまでを返す if(rxStrStored.empty() && rxStr.empty()) return ""; 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に調整済み string tmp= rxStrStored; rxStrStored.erase(); return tmp; } int RN41::setDev_UART(int baud, int bit, int parity, int stop) { rn41.baud(baud); // 力技 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 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; } 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); if(chkReply("AOK\r", 1000).b1) 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).b1) // 500ms return true; sendCMD("\r", false); // 既にCMDモード if(chkReply("?\r", 500).b1) return true; return false; } bool RN41::disconnect() { if(!enterCMD()) return false; // CMD入れず sendCMD("K,"); // rtn KILL ? / ERR ? bool2 find; find= chkReply("KILL\r", 500, "ERR\r"); if(find.b2) { // 既に切断されている sendCMD("---"); // exit CMD mode. return chkReply("END\r", 500).b1; // return true;else// { leds.ON(4);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) { // _read();// rxStrStored += rxStr; timer.start(true); // int cmp2Size= cmp2.size(); int idxCR, idx;//1, idx2;//, idxCut; bool find1, find2; // RxStrのチェック必要じゃね?初期化とか while(true) { _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) idx= rxStr.find(cmp1); if((idx != string::npos) && (idx < idxCR)) find1= true; if(!cmp2.empty()) { //(cmp2.size() != 0) { idx= rxStr.find(cmp2); if((idx != string::npos) && (idx < idxCR)) find2= true; } // CRまで切り取り。findならば削除。見つからなければ目的でない、通常通信とみなし、コピー。 idxCR++;//idxCut= idxCR+ 1; if(rxStr[idxCR] == '\n') idxCR++; // 切り捨てはidxからの切り取りを上書き。コピーは文字数。 if(!(find1 || find2)) rxStrStored += rxStr.substr(0, idxCR); rxStr= rxStr.substr(idxCR); // 切り取りは共通。 if(find1 && find2) // find1有、find2有 return findCmp12; if(find1) return findCmp1; if(find2) 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) { // _read();rxStrStored += rxStr; timer.start(true); int idx, idxCR; while(true) { _read(); idx= rxStr.find(cmp); if(idx != string::npos) { 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::_readIrq(void) { if(rn41.readable()) rxStr += (char)rn41.getc(); return; } void RN41::_read() { // Bufferを吸い尽くす while(rn41.readable()) rxStr += (char)rn41.getc(); 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