RN41/42 control lib. RN41/42 is bluetooth module with class 1 or 2.
Dependencies: StrLib myTimer RingBuffer
RN41.cpp
- Committer:
- AkinoriHashimoto
- Date:
- 2015-11-20
- Revision:
- 5:63925964cbd5
- Parent:
- 4:8b74db22e4c6
File content as of revision 5:63925964cbd5:
#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; // string tmp= rxStrStored+ ringBuf.get(); 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') // LF 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; } bool RN41::reboot() { if(!enterCMD()) return ; // CMD入れず sendCMD("R,1"); // bool2 find= chkReply("Reboot!\r", 100); return chkReply("Reboot!\r", 100).b1; } 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パターンのみのはず。 tmpFind= chkReply_process_wCR(cmp1, cmp2); if(tmpFind.b1) find.b1= true; if(tmpFind.b2) find.b2= true; // CRがrxStrになくなるまで繰り返す。 } else { // CRなし tmpFind= chkReply_process_woCR(cmp1, cmp2, wCR); // この時点で、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; if(wCR && (tmpFind.b1||tmpFind.b2)) flagRtn= false; // CRが出てくるまで待つ if(flagRtn) return find; } if(timer.read_ms(false, false, false) > timeout) return find; wait_ms(1); // 1ms waiting. } // end while } RN41::bool2 RN41::chkReply_process_wCR(string cmp1, string cmp2) { int idx= rxStr.find('\r'); if(rxStr[++idx] == '\n') idx++; // rxStr[idx]は次の文字列のindex // tmpに切り取って確認する。 string tmpStr= rxStr.substr(0, idx); // substr(idx, count) rxStr= rxStr.substr(idx); b2i2 tmpFind= chkReply_find(tmpStr, cmp1, cmp2); if(!(tmpFind.b1 || tmpFind.b2)) // 通常通信 rxStrStored += tmpStr; // cmpと合致していれば、保存しておく必要性がない /* if(tmpFind.b1) rtn.b1= true; if(tmpFind.b2) rtn.b2= true;*/ bool2 rtn; rtn.b1= tmpFind.b1; rtn.b2= tmpFind.b2; return rtn; } RN41::bool2 RN41::chkReply_process_woCR(string cmp1, string cmp2, bool wCR) { b2i2 tmpFind= chkReply_find(rxStr, cmp1, cmp2); // この時点で、tmpとfindの両方がTrueの場合、目的のリプが2回出てきた。おかしい。 // とりあ、そのケースは無視。 // 文字列rxStr処理 if(!wCR && (tmpFind.b1||tmpFind.b2)) { int idx1= 0, idx2= 0; if(tmpFind.b1) idx1= tmpFind.i1+ cmp1.size(); if(tmpFind.b2) idx2= tmpFind.i2+ cmp2.size(); if(idx1 < idx2) idx1= idx2; if(idx1 > 0) rxStr= rxStr.substr(idx1); } bool2 rtn; rtn.b1= tmpFind.b1; rtn.b2= tmpFind.b2; return rtn; } RN41::b2i2 RN41::chkReply_find(string trg, string cmp1, string cmp2) //, bool wCR) // withCR { b2i2 tmp; tmp.b1= tmp.b2= false; tmp.i1= tmp.i2= string::npos; tmp.i1= trg.find(cmp1); if( (tmp.i1= trg.find(cmp1)) != string::npos) tmp.b1= true; if(!cmp2.empty()) if((tmp.i2= trg.find(cmp2)) != string::npos) tmp.b2= true; return tmp; } void RN41::_readIrq(void) { while(rn41.readable()) ringBuf.set((char)rn41.getc()); return; } void RN41::_read() { // Bufferを吸い尽くす this->_readIrq(); // ringBufにSerialバッファからコピーされた。 rxStr += ringBuf.get(); return; } // EOF