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

Dependencies:   StrLib myTimer RingBuffer

Dependents:   Theremin

Committer:
AkinoriHashimoto
Date:
Thu Oct 22 05:02:36 2015 +0000
Revision:
1:5ed110051e39
Parent:
0:812e6b59aa54
Child:
2:3a28bc9332b6
Adj. 15.10.22

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AkinoriHashimoto 0:812e6b59aa54 1 #include "RN41.h"
AkinoriHashimoto 0:812e6b59aa54 2 //#include "SerialBase.h"
AkinoriHashimoto 0:812e6b59aa54 3
AkinoriHashimoto 0:812e6b59aa54 4 const int RN41::NG= 0;
AkinoriHashimoto 0:812e6b59aa54 5 const int RN41::OK= 1;
AkinoriHashimoto 0:812e6b59aa54 6
AkinoriHashimoto 0:812e6b59aa54 7 // PRIVATE
AkinoriHashimoto 0:812e6b59aa54 8 const int RN41::findCmp12= 100;
AkinoriHashimoto 0:812e6b59aa54 9 const int RN41::findCmp1= 101;
AkinoriHashimoto 0:812e6b59aa54 10 const int RN41::findCmp2= 102;
AkinoriHashimoto 0:812e6b59aa54 11
AkinoriHashimoto 0:812e6b59aa54 12 // PUBLIC
AkinoriHashimoto 1:5ed110051e39 13 const int RN41::ERR_Timeout= 201;
AkinoriHashimoto 0:812e6b59aa54 14 const int RN41::ERR_AddrUnder12= 210;
AkinoriHashimoto 0:812e6b59aa54 15 const int RN41::ERR_AddrOver12= 211;
AkinoriHashimoto 0:812e6b59aa54 16 const int RN41::ERR_Connect= 220;
AkinoriHashimoto 0:812e6b59aa54 17 const int RN41::FAIL_Connect= 221;
AkinoriHashimoto 0:812e6b59aa54 18 const int RN41::ERR_EnterCmdMode= 230;
AkinoriHashimoto 0:812e6b59aa54 19 const int RN41::ERR_Disconnect= 240;
AkinoriHashimoto 0:812e6b59aa54 20
AkinoriHashimoto 0:812e6b59aa54 21 const int RN41::ERR_NameSize= 310;
AkinoriHashimoto 0:812e6b59aa54 22
AkinoriHashimoto 0:812e6b59aa54 23 /*
AkinoriHashimoto 0:812e6b59aa54 24 const int RN41::None= 10;
AkinoriHashimoto 0:812e6b59aa54 25 const int RN41::Odd= 11;
AkinoriHashimoto 0:812e6b59aa54 26 const int RN41::Even= 12;
AkinoriHashimoto 0:812e6b59aa54 27 */
AkinoriHashimoto 0:812e6b59aa54 28
AkinoriHashimoto 0:812e6b59aa54 29
AkinoriHashimoto 0:812e6b59aa54 30
AkinoriHashimoto 0:812e6b59aa54 31 RN41::RN41(PinName TX, PinName RX, int baudrate, int bit, int parity, int stop, bool CRLN)
AkinoriHashimoto 0:812e6b59aa54 32 : rn41(TX, RX)
AkinoriHashimoto 0:812e6b59aa54 33 {
AkinoriHashimoto 1:5ed110051e39 34 this->setDev_UART(baudrate, bit, parity, stop);
AkinoriHashimoto 1:5ed110051e39 35 cr= '\r';
AkinoriHashimoto 0:812e6b59aa54 36 if(CRLN)
AkinoriHashimoto 1:5ed110051e39 37 cr= "\r\n";
AkinoriHashimoto 0:812e6b59aa54 38 }
AkinoriHashimoto 0:812e6b59aa54 39
AkinoriHashimoto 0:812e6b59aa54 40 int RN41::connect(string addr)
AkinoriHashimoto 0:812e6b59aa54 41 {
AkinoriHashimoto 0:812e6b59aa54 42 addr= toAlpanumeric(addr, true);
AkinoriHashimoto 0:812e6b59aa54 43 int idx= addr.size();
AkinoriHashimoto 0:812e6b59aa54 44 // ex. 0006:66:72:6e05\r ->000666726e05.
AkinoriHashimoto 0:812e6b59aa54 45 if(idx < 12)
AkinoriHashimoto 0:812e6b59aa54 46 return ERR_AddrUnder12;
AkinoriHashimoto 0:812e6b59aa54 47 if(idx > 12)
AkinoriHashimoto 0:812e6b59aa54 48 return ERR_AddrOver12;
AkinoriHashimoto 0:812e6b59aa54 49
AkinoriHashimoto 0:812e6b59aa54 50 if(!enterCMD())
AkinoriHashimoto 0:812e6b59aa54 51 return ERR_EnterCmdMode; // CMD入れず
AkinoriHashimoto 0:812e6b59aa54 52 if(!disconnect())
AkinoriHashimoto 0:812e6b59aa54 53 return ERR_Disconnect;
AkinoriHashimoto 0:812e6b59aa54 54 if(!enterCMD())
AkinoriHashimoto 0:812e6b59aa54 55 return ERR_EnterCmdMode; // CMD入れず
AkinoriHashimoto 0:812e6b59aa54 56
AkinoriHashimoto 0:812e6b59aa54 57 sendCMD("C,"+ addr);
AkinoriHashimoto 0:812e6b59aa54 58 int status;
AkinoriHashimoto 0:812e6b59aa54 59
AkinoriHashimoto 1:5ed110051e39 60 status= chkReply("TRYING\r", 1000, "ERR\r"); // within waiting for Reply
AkinoriHashimoto 0:812e6b59aa54 61
AkinoriHashimoto 0:812e6b59aa54 62 if(status == findCmp2)
AkinoriHashimoto 0:812e6b59aa54 63 return ERR_Connect;
AkinoriHashimoto 0:812e6b59aa54 64 else if(status == findCmp1) {
AkinoriHashimoto 0:812e6b59aa54 65 // Trying to connect to remote Bluetooth dev.
AkinoriHashimoto 1:5ed110051e39 66 status= chkReply("CONNECT,", 10000, "CONNECT failed\r"); // wait 10s(max)
AkinoriHashimoto 0:812e6b59aa54 67 if(status == findCmp1)
AkinoriHashimoto 0:812e6b59aa54 68 return OK;
AkinoriHashimoto 0:812e6b59aa54 69 else if(status == findCmp2)
AkinoriHashimoto 0:812e6b59aa54 70 return FAIL_Connect;
AkinoriHashimoto 1:5ed110051e39 71 else if(status == ERR_Timeout)
AkinoriHashimoto 1:5ed110051e39 72 return ERR_Timeout;
AkinoriHashimoto 0:812e6b59aa54 73 }
AkinoriHashimoto 0:812e6b59aa54 74 return 1234;
AkinoriHashimoto 0:812e6b59aa54 75 }
AkinoriHashimoto 0:812e6b59aa54 76
AkinoriHashimoto 0:812e6b59aa54 77
AkinoriHashimoto 0:812e6b59aa54 78 string RN41::getLine()
AkinoriHashimoto 0:812e6b59aa54 79 {
AkinoriHashimoto 0:812e6b59aa54 80 read();
AkinoriHashimoto 0:812e6b59aa54 81 // CRまでを返す
AkinoriHashimoto 0:812e6b59aa54 82
AkinoriHashimoto 0:812e6b59aa54 83 if(str4GetLine.size()==0 && rxStr.size()==0)
AkinoriHashimoto 0:812e6b59aa54 84 return "";
AkinoriHashimoto 0:812e6b59aa54 85
AkinoriHashimoto 1:5ed110051e39 86 int idx= rxStr.rfind(cr);
AkinoriHashimoto 0:812e6b59aa54 87 if(idx == string::npos) // not find CR!
AkinoriHashimoto 0:812e6b59aa54 88 return str4GetLine; // ダメじゃね??
AkinoriHashimoto 0:812e6b59aa54 89
AkinoriHashimoto 1:5ed110051e39 90 idx += cr.size(); // \rなら+1、\r\nは+2
AkinoriHashimoto 0:812e6b59aa54 91 string rtn= str4GetLine;
AkinoriHashimoto 0:812e6b59aa54 92 rtn += rxStr.substr(0, idx); // 切り取り
AkinoriHashimoto 0:812e6b59aa54 93 rxStr= rxStr.substr(idx);
AkinoriHashimoto 0:812e6b59aa54 94 // sendHC05("debug 40");
AkinoriHashimoto 0:812e6b59aa54 95 return rtn;
AkinoriHashimoto 0:812e6b59aa54 96 }
AkinoriHashimoto 0:812e6b59aa54 97
AkinoriHashimoto 0:812e6b59aa54 98
AkinoriHashimoto 1:5ed110051e39 99 int RN41::setDev_UART(int baud, int bit, int parity, int stop)
AkinoriHashimoto 1:5ed110051e39 100 {
AkinoriHashimoto 1:5ed110051e39 101 rn41.baud(baud);
AkinoriHashimoto 1:5ed110051e39 102
AkinoriHashimoto 1:5ed110051e39 103 // 力技
AkinoriHashimoto 1:5ed110051e39 104 if (parity == SerialBase::Odd)
AkinoriHashimoto 1:5ed110051e39 105 rn41.format(bit, SerialBase::Odd, stop);
AkinoriHashimoto 1:5ed110051e39 106 else if (parity == SerialBase::Even)
AkinoriHashimoto 1:5ed110051e39 107 rn41.format(bit, SerialBase::Even, stop); // 8bit, NonParity, 1stopbit
AkinoriHashimoto 1:5ed110051e39 108 else if (parity == SerialBase::None)
AkinoriHashimoto 1:5ed110051e39 109 rn41.format(bit, SerialBase::None, stop); // 8bit, NonParity, 1stopbit
AkinoriHashimoto 1:5ed110051e39 110 else
AkinoriHashimoto 1:5ed110051e39 111 return NG;
AkinoriHashimoto 1:5ed110051e39 112
AkinoriHashimoto 1:5ed110051e39 113 return OK;
AkinoriHashimoto 1:5ed110051e39 114 }
AkinoriHashimoto 1:5ed110051e39 115
AkinoriHashimoto 0:812e6b59aa54 116
AkinoriHashimoto 0:812e6b59aa54 117 int RN41::setDev_Name(string str, bool usingAddr)
AkinoriHashimoto 0:812e6b59aa54 118 {
AkinoriHashimoto 0:812e6b59aa54 119 int strSize= str.size();
AkinoriHashimoto 0:812e6b59aa54 120 if((strSize==0) || (20<=strSize) || (usingAddr && 15<=strSize))
AkinoriHashimoto 0:812e6b59aa54 121 return ERR_NameSize;
AkinoriHashimoto 0:812e6b59aa54 122
AkinoriHashimoto 0:812e6b59aa54 123 // 特殊文字チェックは不要っぽい
AkinoriHashimoto 0:812e6b59aa54 124
AkinoriHashimoto 0:812e6b59aa54 125 string cmd;
AkinoriHashimoto 0:812e6b59aa54 126 if(usingAddr)
AkinoriHashimoto 0:812e6b59aa54 127 cmd= "S-,";
AkinoriHashimoto 0:812e6b59aa54 128 else
AkinoriHashimoto 0:812e6b59aa54 129 cmd= "SN,";
AkinoriHashimoto 0:812e6b59aa54 130
AkinoriHashimoto 0:812e6b59aa54 131 if(!enterCMD())
AkinoriHashimoto 0:812e6b59aa54 132 return ERR_EnterCmdMode; // CMD入れず
AkinoriHashimoto 0:812e6b59aa54 133
AkinoriHashimoto 0:812e6b59aa54 134 sendCMD(cmd+ str);
AkinoriHashimoto 0:812e6b59aa54 135 int status;
AkinoriHashimoto 0:812e6b59aa54 136 status= chkReply("AOK\r", 1000);
AkinoriHashimoto 0:812e6b59aa54 137 if(status == findCmp1)
AkinoriHashimoto 0:812e6b59aa54 138 return OK;
AkinoriHashimoto 0:812e6b59aa54 139
AkinoriHashimoto 0:812e6b59aa54 140 return NG;
AkinoriHashimoto 0:812e6b59aa54 141 }
AkinoriHashimoto 0:812e6b59aa54 142
AkinoriHashimoto 0:812e6b59aa54 143
AkinoriHashimoto 0:812e6b59aa54 144 void RN41::sendCMD(string str, bool addCR)
AkinoriHashimoto 0:812e6b59aa54 145 {
AkinoriHashimoto 0:812e6b59aa54 146 if(addCR)
AkinoriHashimoto 0:812e6b59aa54 147 str += '\r';
AkinoriHashimoto 0:812e6b59aa54 148 rn41.printf(str.c_str());
AkinoriHashimoto 0:812e6b59aa54 149 return;
AkinoriHashimoto 0:812e6b59aa54 150 }
AkinoriHashimoto 1:5ed110051e39 151 void RN41::sendLine(string str, bool addCR)
AkinoriHashimoto 0:812e6b59aa54 152 {
AkinoriHashimoto 0:812e6b59aa54 153 if(addCR)
AkinoriHashimoto 0:812e6b59aa54 154 str += "\r\n";
AkinoriHashimoto 0:812e6b59aa54 155 rn41.printf(str.c_str());
AkinoriHashimoto 0:812e6b59aa54 156 return;
AkinoriHashimoto 0:812e6b59aa54 157 }
AkinoriHashimoto 0:812e6b59aa54 158
AkinoriHashimoto 0:812e6b59aa54 159
AkinoriHashimoto 0:812e6b59aa54 160
AkinoriHashimoto 0:812e6b59aa54 161 bool RN41::enterCMD()
AkinoriHashimoto 0:812e6b59aa54 162 {
AkinoriHashimoto 0:812e6b59aa54 163 sendCMD("$$$", false);
AkinoriHashimoto 1:5ed110051e39 164 if(chkReply("CMD\r", 500) == findCmp1) // 500ms
AkinoriHashimoto 0:812e6b59aa54 165 return true;
AkinoriHashimoto 1:5ed110051e39 166
AkinoriHashimoto 0:812e6b59aa54 167
AkinoriHashimoto 0:812e6b59aa54 168 sendCMD("\r", false); // 既にCMDモード
AkinoriHashimoto 1:5ed110051e39 169 if(chkReply("?\r", 500) == findCmp1)
AkinoriHashimoto 0:812e6b59aa54 170 return true;
AkinoriHashimoto 0:812e6b59aa54 171 return false;
AkinoriHashimoto 0:812e6b59aa54 172 }
AkinoriHashimoto 0:812e6b59aa54 173
AkinoriHashimoto 0:812e6b59aa54 174
AkinoriHashimoto 0:812e6b59aa54 175
AkinoriHashimoto 0:812e6b59aa54 176 bool RN41::disconnect()
AkinoriHashimoto 0:812e6b59aa54 177 {
AkinoriHashimoto 1:5ed110051e39 178 if(!enterCMD())
AkinoriHashimoto 1:5ed110051e39 179 return false; // CMD入れず
AkinoriHashimoto 0:812e6b59aa54 180 sendCMD("K,"); // rtn KILL ? / ERR ?
AkinoriHashimoto 0:812e6b59aa54 181 int status;
AkinoriHashimoto 0:812e6b59aa54 182
AkinoriHashimoto 0:812e6b59aa54 183 status= chkReply("KILL\r", 500, "ERR\r");
AkinoriHashimoto 0:812e6b59aa54 184 if(status == findCmp2) { // 既に切断されている
AkinoriHashimoto 0:812e6b59aa54 185 sendCMD("---"); // exit CMD mode.
AkinoriHashimoto 0:812e6b59aa54 186 if(chkReply("END\r", 500) == findCmp1)
AkinoriHashimoto 0:812e6b59aa54 187 return true;
AkinoriHashimoto 0:812e6b59aa54 188 else// { leds.ON(4);
AkinoriHashimoto 0:812e6b59aa54 189 return false; // どういう状況か不明
AkinoriHashimoto 0:812e6b59aa54 190 } else if(status == findCmp1) {
AkinoriHashimoto 0:812e6b59aa54 191 if(chkReply_woCR("DISCONNECT", 5000)) // CR無いかも?
AkinoriHashimoto 0:812e6b59aa54 192 return true;
AkinoriHashimoto 1:5ed110051e39 193 else
AkinoriHashimoto 0:812e6b59aa54 194 return false; // どういう状況か不明
AkinoriHashimoto 1:5ed110051e39 195 }
AkinoriHashimoto 0:812e6b59aa54 196 return false;
AkinoriHashimoto 0:812e6b59aa54 197 }
AkinoriHashimoto 0:812e6b59aa54 198
AkinoriHashimoto 0:812e6b59aa54 199 int RN41::chkReply(string cmp1, int timeout, string cmp2)
AkinoriHashimoto 0:812e6b59aa54 200 {
AkinoriHashimoto 1:5ed110051e39 201 timer.start(true);
AkinoriHashimoto 0:812e6b59aa54 202
AkinoriHashimoto 0:812e6b59aa54 203 int cmp2Size= cmp2.size();
AkinoriHashimoto 1:5ed110051e39 204 int idxCR, idx1, idx2;
AkinoriHashimoto 0:812e6b59aa54 205 bool find1, find2;
AkinoriHashimoto 0:812e6b59aa54 206
AkinoriHashimoto 1:5ed110051e39 207 // RxStrのチェック必要じゃね?初期化とか
AkinoriHashimoto 1:5ed110051e39 208 int idxCut;
AkinoriHashimoto 1:5ed110051e39 209 while(true) {
AkinoriHashimoto 1:5ed110051e39 210 if(timer.read_ms(false, false, false) > timeout)
AkinoriHashimoto 1:5ed110051e39 211 return ERR_Timeout;
AkinoriHashimoto 0:812e6b59aa54 212 read();
AkinoriHashimoto 1:5ed110051e39 213 idxCR= rxStr.find('\r');
AkinoriHashimoto 0:812e6b59aa54 214 if(idxCR != string::npos) { // CR found.
AkinoriHashimoto 1:5ed110051e39 215
AkinoriHashimoto 0:812e6b59aa54 216 find1= find2= false;
AkinoriHashimoto 1:5ed110051e39 217 // idx1: 0< or npos, idx2: 0< or npos(notfined or size0)
AkinoriHashimoto 1:5ed110051e39 218 //idx1(~CR) -> idx2(~CR)
AkinoriHashimoto 0:812e6b59aa54 219 idx1= rxStr.find(cmp1);
AkinoriHashimoto 1:5ed110051e39 220 if((idx1 != string::npos) && (idx1 < idxCR))
AkinoriHashimoto 1:5ed110051e39 221 find1= true;
AkinoriHashimoto 1:5ed110051e39 222
AkinoriHashimoto 1:5ed110051e39 223 if(cmp2Size != 0) {
AkinoriHashimoto 0:812e6b59aa54 224 idx2= rxStr.find(cmp2);
AkinoriHashimoto 1:5ed110051e39 225 if((idx2 != string::npos) && (idx2 < idxCR))
AkinoriHashimoto 0:812e6b59aa54 226 find2= true;
AkinoriHashimoto 1:5ed110051e39 227 }
AkinoriHashimoto 0:812e6b59aa54 228
AkinoriHashimoto 0:812e6b59aa54 229 // CRまで切り取り。findならば切り捨て、見つからなければコピー後切り捨て
AkinoriHashimoto 0:812e6b59aa54 230 idxCut= idxCR+ 1;
AkinoriHashimoto 0:812e6b59aa54 231 if(rxStr[idxCut] == '\n')
AkinoriHashimoto 0:812e6b59aa54 232 idxCut++;
AkinoriHashimoto 0:812e6b59aa54 233 // 切り捨てはidxからの切り取りを上書き。コピーは文字数なので、idxが-1まで。
AkinoriHashimoto 0:812e6b59aa54 234 if(!(find1 || find2))
AkinoriHashimoto 0:812e6b59aa54 235 str4GetLine= rxStr.substr(0, idxCut);
AkinoriHashimoto 0:812e6b59aa54 236 rxStr= rxStr.substr(idxCut); // 切り取りは共通。
AkinoriHashimoto 0:812e6b59aa54 237
AkinoriHashimoto 0:812e6b59aa54 238 if(find1 && find2) // find1有、find2有
AkinoriHashimoto 0:812e6b59aa54 239 return findCmp12;
AkinoriHashimoto 0:812e6b59aa54 240 if(find1)
AkinoriHashimoto 0:812e6b59aa54 241 return findCmp1;
AkinoriHashimoto 0:812e6b59aa54 242 if(find2)
AkinoriHashimoto 0:812e6b59aa54 243 return findCmp2;
AkinoriHashimoto 0:812e6b59aa54 244 // CR内にCMP無い場合は、ループへ
AkinoriHashimoto 1:5ed110051e39 245 } // (idxCR != string::npos)
AkinoriHashimoto 1:5ed110051e39 246 wait_ms(2); // 1ms waiting.
AkinoriHashimoto 0:812e6b59aa54 247 } // end for
AkinoriHashimoto 0:812e6b59aa54 248 }
AkinoriHashimoto 0:812e6b59aa54 249
AkinoriHashimoto 0:812e6b59aa54 250
AkinoriHashimoto 0:812e6b59aa54 251 bool RN41::chkReply_woCR(string cmp, int timeout)
AkinoriHashimoto 0:812e6b59aa54 252 {
AkinoriHashimoto 1:5ed110051e39 253 timer.start(true);
AkinoriHashimoto 0:812e6b59aa54 254
AkinoriHashimoto 0:812e6b59aa54 255 int idx;
AkinoriHashimoto 1:5ed110051e39 256 while(true) {
AkinoriHashimoto 1:5ed110051e39 257 if(timer.read_ms(false, false, false) > timeout)
AkinoriHashimoto 0:812e6b59aa54 258 return false;
AkinoriHashimoto 1:5ed110051e39 259
AkinoriHashimoto 0:812e6b59aa54 260 read();
AkinoriHashimoto 0:812e6b59aa54 261 idx= rxStr.find(cmp);
AkinoriHashimoto 1:5ed110051e39 262
AkinoriHashimoto 0:812e6b59aa54 263 if(idx != string::npos) {
AkinoriHashimoto 1:5ed110051e39 264 idx= rxStr.find('\r');
AkinoriHashimoto 1:5ed110051e39 265 // find CRLF
AkinoriHashimoto 0:812e6b59aa54 266 if(idx == string::npos)
AkinoriHashimoto 0:812e6b59aa54 267 rxStr= "";
AkinoriHashimoto 0:812e6b59aa54 268 else {
AkinoriHashimoto 0:812e6b59aa54 269 idx++;
AkinoriHashimoto 0:812e6b59aa54 270 if(rxStr[idx] == '\n')
AkinoriHashimoto 0:812e6b59aa54 271 idx++;
AkinoriHashimoto 0:812e6b59aa54 272 rxStr= rxStr.substr(idx);
AkinoriHashimoto 0:812e6b59aa54 273 }
AkinoriHashimoto 0:812e6b59aa54 274 return true;
AkinoriHashimoto 0:812e6b59aa54 275 }
AkinoriHashimoto 1:5ed110051e39 276 wait_ms(2);
AkinoriHashimoto 0:812e6b59aa54 277 }
AkinoriHashimoto 0:812e6b59aa54 278 }
AkinoriHashimoto 0:812e6b59aa54 279
AkinoriHashimoto 0:812e6b59aa54 280
AkinoriHashimoto 0:812e6b59aa54 281
AkinoriHashimoto 0:812e6b59aa54 282
AkinoriHashimoto 0:812e6b59aa54 283 void RN41::read()
AkinoriHashimoto 0:812e6b59aa54 284 {
AkinoriHashimoto 0:812e6b59aa54 285 if(!rn41.readable())
AkinoriHashimoto 0:812e6b59aa54 286 return;
AkinoriHashimoto 0:812e6b59aa54 287
AkinoriHashimoto 0:812e6b59aa54 288 // Bufferを吸い尽くす
AkinoriHashimoto 1:5ed110051e39 289 while(true) {
AkinoriHashimoto 0:812e6b59aa54 290 rxStr += (char)rn41.getc();
AkinoriHashimoto 0:812e6b59aa54 291 if(!rn41.readable())
AkinoriHashimoto 1:5ed110051e39 292 return; // Bufferになくなった
AkinoriHashimoto 0:812e6b59aa54 293 } // end for
AkinoriHashimoto 1:5ed110051e39 294 }
AkinoriHashimoto 1:5ed110051e39 295
AkinoriHashimoto 1:5ed110051e39 296 // EOF