Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: StrLib myTimer RingBuffer
Revision 0:812e6b59aa54, committed 2015-10-20
- Comitter:
- AkinoriHashimoto
- Date:
- Tue Oct 20 01:32:17 2015 +0000
- Child:
- 1:5ed110051e39
- Commit message:
- beta publish.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/RN41.cpp Tue Oct 20 01:32:17 2015 +0000
@@ -0,0 +1,339 @@
+#include "RN41.h"
+//#include "SerialBase.h"
+
+//extern void sendHC05(string);
+
+
+
+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_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)
+{
+ rn41.baud(baudrate);
+ /*
+ Parity _parity= SerialBase::None; // enum
+ if(parity == 'O')
+ _parity= SerialBase::Odd;
+ if(parity == 'E')
+ _parity= SerialBase::Even;
+ rn41.format(bit, _parity, stop); // 8bit, NonParity, 1stopbit
+ */
+
+ // 力技
+ 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
+
+ CR= '\r';
+ if(CRLN)
+ CR= "\r\n";
+}
+
+
+int RN41::connect(string addr)
+{
+ timerLocal.reset();
+ timerLocal.start();
+
+ 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入れず
+// sendHC05("test 100");
+ if(!disconnect())
+ return ERR_Disconnect;
+ if(!enterCMD())
+ return ERR_EnterCmdMode; // CMD入れず
+
+ // BT addr check success;
+ sendCMD("C,"+ addr);
+ int status;
+
+// wait(1.0);read();sendHC05("--"+ rxStr+ "**");
+
+ status= chkReply("TRYING\r", 1000, "ERR\r");
+ if(status == findCmp2)
+ return ERR_Connect;
+ else if(status == findCmp1) {
+ // Trying to connect to remote Bluetooth dev.
+
+// wait(7.0); read(); sendHC05(rxStr);
+ timerLocal.reset();
+ timerLocal.start();
+ status= chkReply("CONNECT,", 10000, "CONNECT failed\r"); // wait 10s
+
+// sendHC05("Time of Create-Connection: "+ I2A(timerLocal.read_ms())+ " ms.");
+
+ if(status == findCmp1)
+ return OK;
+ else if(status == findCmp2)
+ return FAIL_Connect;
+ } else {
+// sendHC05("connect:"+ I2A(status));
+ }
+ return 1234;
+}
+
+
+
+
+string RN41::getLine()
+{
+ read();
+ // CRまでを返す
+
+//sendHC05("debug 10");
+ if(str4GetLine.size()==0 && rxStr.size()==0)
+ return "";
+
+// trying->Connect待ちをTickerにすると、そこんとの除外処理が必須。
+// sendHC05("debug 20");
+
+ // rxStr.size() > 0
+ int idx= rxStr.rfind(CR);
+// sendHC05("rxStr: "+ rxStr); sendHC05("idxCR: "+ I2A(idx));
+ if(idx == string::npos) // not find CR!
+ return str4GetLine; // ダメじゃね??
+
+// sendHC05("debug 30");
+ // rxStr has CR.
+ 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;
+}
+
+
+
+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);
+ int status;
+// wait(1.0);read();sendHC05("--"+ rxStr+ "**");
+ status= chkReply("AOK\r", 1000);
+ if(status == findCmp1)
+ 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) == findCmp1) { // 500ms
+// sendHC05("returned CMD.");
+ return true;
+ }
+
+ sendCMD("\r", false); // 既にCMDモード
+ if(chkReply("?\r", 500) == findCmp1) {
+// sendHC05("Already CmdMode.");
+ return true;
+ }
+ return false;
+}
+
+
+
+bool RN41::disconnect()
+{
+ // if(!enterCMD()) return false; // CMD入れず
+
+ sendCMD("K,"); // rtn KILL ? / ERR ?
+ int status;
+// wait(6.0); read(); sendHC05("in disconnect; \t"+ rxStr);
+
+ status= chkReply("KILL\r", 500, "ERR\r");
+ if(status == findCmp2) { // 既に切断されている
+ sendCMD("---"); // exit CMD mode.
+ if(chkReply("END\r", 500) == findCmp1)
+ return true;
+ else// { leds.ON(4);
+ return false; // どういう状況か不明
+ } else if(status == findCmp1) {
+// if(chkReply("DISCONNECT", 2000) == findCmp1)
+ if(chkReply_woCR("DISCONNECT", 5000)) // CR無いかも?
+ return true;
+ else //{ leds.ON(3);
+ return false; // どういう状況か不明
+ }// else { return false; }
+ return false;
+}
+
+
+
+
+int RN41::chkReply(string cmp1, int timeout, string cmp2)
+{
+ timerLocal.reset();
+ timerLocal.start();
+
+ int cmp2Size= cmp2.size();
+ int idxCR, idx1, idx2;//= string::npos;
+ bool find1, find2;
+ for(;;) {
+ if(timerLocal.read_ms() > timeout)
+ return NG;
+
+ read();
+ idxCR= rxStr.find_first_of('\r');
+ if(idxCR != string::npos) { // CR found.
+ idx1= idx2= string::npos; // -1
+ find1= find2= false;
+ idx1= rxStr.find(cmp1);
+ if(cmp2Size != 0)
+ idx2= rxStr.find(cmp2);
+
+ // idx1: 0< or npos, idx2: 0< or npos(notfined or size0)
+ int idxCut;
+ //idx1(~CR) -> idx2(~CR)
+ if(idx1 != string::npos)
+ if(idx1 < idxCR)
+ find1= true;
+ if(idx2 != string::npos)
+ if(idx2 < idxCR)
+ find2= true;
+
+//sendHC05("++"+ rxStr+ "**");
+//sendHC05("idx1:"+cmp1+":"+ I2A(idx1)+ "\tidx2:"+cmp2+":"+ I2A(idx2)+ "\tidxCR:"+ I2A(idxCR));
+
+ // CRまで切り取り。findならば切り捨て、見つからなければコピー後切り捨て
+ idxCut= idxCR+ 1;
+ if(rxStr[idxCut] == '\n')
+ idxCut++;
+ // 切り捨てはidxからの切り取りを上書き。コピーは文字数なので、idxが-1まで。
+ if(!(find1 || find2))
+ str4GetLine= rxStr.substr(0, idxCut);
+ rxStr= rxStr.substr(idxCut); // 切り取りは共通。
+
+ if(find1 && find2) // find1有、find2有
+ return findCmp12;
+ if(find1)
+ return findCmp1;
+ if(find2)
+ return findCmp2;
+ // CR内にCMP無い場合は、ループへ
+ }
+ } // end for
+}
+
+
+bool RN41::chkReply_woCR(string cmp, int timeout)
+{
+ timerLocal.reset();
+ timerLocal.start();
+
+ int idx;
+ for(;;) {
+ if(timerLocal.read_ms() > timeout) {
+// sendHC05("in chkReply; "+ rxStr);
+ return false;
+ }
+ read();
+ idx= rxStr.find(cmp);
+ if(idx != string::npos) {
+ // めんどいから消去する。
+ idx= rxStr.find_first_of('\r');
+ if(idx == string::npos)
+ rxStr= "";
+ else {
+ idx++;
+ if(rxStr[idx] == '\n')
+ idx++;
+ rxStr= rxStr.substr(idx);
+ }
+// rxStr= "";
+ return true;
+ }
+ }
+}
+
+
+
+
+void RN41::read()
+{
+ if(!rn41.readable())
+ return;
+
+ // Bufferを吸い尽くす
+// char ch;
+ for(;;) {
+// char ch= rn41.getc(); // 1文字取る
+// ch= rn41.getc(); // 1文字取る
+// rxStr += ch; // 上書き前に退避
+ rxStr += (char)rn41.getc();
+ if(!rn41.readable())
+ return; //break; // Bufferになくなった
+ } // end for
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/RN41.h Tue Oct 20 01:32:17 2015 +0000
@@ -0,0 +1,86 @@
+/** RN41/42 is Bluetooth module. RN41 is calss 1, RN42 is class 2.
+ * RN42 refer to http://akizukidenshi.com/catalog/g/gM-07612/ .
+ */
+
+#pragma once
+
+#include "mbed.h"
+#include "StrLib.h"
+
+/*
+ * cmdで送る改行コードは、CRのみ。LFは文字として認識されるので?となる。
+ * RN41 Returns (default); AOK(valid cmd), ERR(invalid cmod), ?(unrecongnized cmd).
+
+%を付ける初期化処理必須
+
+*/
+
+
+/** Bluetooth module RN41/42 control class.
+ *
+ */
+class RN41
+{
+public:
+
+// static const int
+ static const int NG, OK;//= 1;
+ static const int ERR_AddrUnder12, ERR_AddrOver12, ERR_Connect, FAIL_Connect;
+ static const int ERR_EnterCmdMode, ERR_Disconnect;
+
+// static const int None, Odd, Even;
+ static const int ERR_NameSize;
+
+ /** Create Serial port to RN41. for LPC1768
+ * @param TX, RX; Serial port.
+ * @param baud-rate; Baud rate (bps).
+ * @param bit, parity, stop; Default: 1Stopbit, NoneParity, 1StopBit.
+ * -- parity select; N(None), O(Odd), E(Even).
+ * @param CRLN; true -> CR&LN (\r\n), false -> CR only (\r).
+ */
+ RN41(PinName TX, PinName RX, int baudrate, int bit=8, int parity=SerialBase::None, int stop=1, bool CRLN=true);
+
+ /**
+ * RxStrのCRまでを返す。
+ */
+ string getLine();
+
+ /**
+ *
+ */
+ void sendCMD( string str, bool addCR=true);
+ void sendLINE(string str, bool addCR=true);
+
+
+ int setDev_Name(string str, bool usingAddr=true);
+ int setDev_UART(int boad, int stop=1, int parity=SerialBase::None);
+
+
+// Command to RN41
+ bool enterCMD();
+ int connect(string addr); // 必ず、Checkを呼ぶこと。2-5sかかるよ
+ bool disconnect();
+
+private:
+ Serial rn41;
+ string CR;
+ string rxStr, str4GetLine; // 内部バッファ。read()での保管用と、GetLineまでの保管用。
+
+ Timer timerLocal;
+
+ static const int findCmp1, findCmp2, findCmp12;
+ /** check reply from RN41.
+ * @Param cmp; string to compare
+ * @Param timeout; timeout [ms]
+ * @return bool; true: ok, false: NG.
+ */
+ int chkReply(string cmp1, int timeout, string cmp2="");
+
+ bool chkReply_woCR(string cmp, int timeout);
+
+ /** Just copy to rxStr from Buffer.
+ *
+ */
+ void read();
+
+};
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/StrLib.lib Tue Oct 20 01:32:17 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/AkinoriHashimoto/code/StrLib/#7bc89a64bfbd