PQ_Hybrid_Electrical_Equipment_Team / XbeeApiLib

Dependents:   XbeeAPI Hybrid_main_FirstEdtion

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers XbeeApiLib.cpp Source File

XbeeApiLib.cpp

00001 #include "mbed.h"
00002 #include <XbeeApiLib.h>
00003 #include <string>
00004 
00005 XbeeApi::XbeeApi(PinName Tx, PinName Rx, int BaudRate, void (*onPacketReceived)(int, char*)) : Xbee(Tx, Rx, BaudRate){
00006     //Xbee = Serial(Tx, Rx, BaudRate);
00007     //Xbee.baud(BaudRate);
00008     
00009     HopLimit = 0;
00010     for(int i = 0;i < 4;i++){
00011         address[i].IsAvailable = false;
00012     }
00013     IsTransmitting = false;
00014     SetInterrupt(true);
00015     OnPacketReceived = onPacketReceived;
00016 }
00017 
00018 void XbeeApi::SetAddress(int Num, unsigned long HIGH, unsigned long LOW){
00019     for(int i = 0;i < 4;i++){
00020         address[Num].ADR[3 - i] = reinterpret_cast<char (&)[sizeof(HIGH)]>(HIGH)[i];
00021         address[Num].ADR[7 - i] = reinterpret_cast<char (&)[sizeof(LOW)]>(LOW)[i];
00022     }
00023     address[Num].IsAvailable = false;
00024     address[Num].sum = 0;
00025     //EndPacket()でチェックサムを計算する際、宛先アドレスもチェックサムに含まれる
00026     //宛先アドレスは頻繁に変更されないので、アドレス分の合計だけを先にまとめて計算しておく
00027     for(int i = 0;i < 8;i++){
00028         address[Num].sum += address[Num].ADR[i];
00029     }
00030     address[Num].ADR16bit[0] = 0x00;
00031     address[Num].ADR16bit[1] = 0x00;
00032 }
00033 
00034 //
00035 //char StartWith: 送信されるデータの最初の1バイトに送信内容のタグとしての役割を持たせている
00036 //これにより、受信側では送信されてきたバイナリデータをどのような形式で読み取ればよいのか判断する
00037 void XbeeApi::StartPacket(char StartWith){
00038     CheckSum = 0x12;
00039     buf[17] = StartWith;
00040     itr = 18;
00041 }
00042 
00043 //文字列を送信バッファに書き込む
00044 void XbeeApi::Write(string val){
00045     int length = val.length();
00046     if(length < 128 - itr){     //送信バッファの空きよりも文字列が長い場合は何もしない
00047         for(int i = 0;i < length;i++){
00048             buf[itr + i] = val.c_str()[i];
00049         }
00050         itr += length;
00051     }else{
00052         buf[17] = 0x00;
00053         EndPacket();
00054     }
00055 }
00056 
00057 //int型の数値をバイト列として書き込む
00058 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
00059 void XbeeApi::Write(int val){
00060     if(sizeof(val) < 128 - itr){
00061         for(int i = 0;i < sizeof(val);i++){
00062             buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
00063         }
00064         itr += sizeof(val);
00065     }else{
00066         buf[17] = 0x00;
00067         EndPacket();
00068     }
00069 }
00070 
00071 //long型の数値をバイト列として書き込む
00072 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
00073 void XbeeApi::Write(long long val){
00074     if(sizeof(val) < 128 - itr){
00075         for(int i = 0;i < sizeof(val);i++){
00076             buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
00077         }
00078         itr += sizeof(val);
00079     }else{
00080         buf[17] = 0x00;
00081         EndPacket();
00082     }
00083 }
00084 
00085 //double型の数値をバイト列として書き込む
00086 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
00087 void XbeeApi::Write(double val){
00088     if(sizeof(val) < 128 - itr){
00089         for(int i = 0;i < sizeof(val);i++){
00090             buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
00091         }
00092         itr += sizeof(val);
00093     }else{
00094         buf[17] = 0x00;
00095         EndPacket();
00096     }
00097 }
00098 
00099 //float型の数値をバイト列として書き込む
00100 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
00101 void XbeeApi::Write(float val){
00102     if(sizeof(val) < 128 - itr){
00103         for(int i = 0;i < sizeof(val);i++){
00104             buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
00105         }
00106         itr += sizeof(val);
00107     }else{
00108         buf[17] = 0x00;
00109         EndPacket();
00110     }
00111 }
00112 
00113 void XbeeApi::EndPacket(){
00114     if(itr != 0){
00115         buf[0] = 0x7E;    //パケットの先頭を表す
00116         buf[1] = (char)(itr - 3) >> 8;
00117         buf[2] = (char)(itr - 3) & 0x00FF;
00118         buf[3] = 0x10;
00119         buf[4] = 0x00;         //ここを01にするとxbeeは送信の成否の判定を行うようになる(クソ重い)
00120         buf[15] = 0x01;
00121         buf[16] = 0x01;         //0x01:送りっぱなし
00122         for(int i = 17;i < itr; i++){
00123             CheckSum += buf[i];
00124         }
00125         BytesToTransmit = itr + 1;
00126         NextTransmitIndex = BytesToTransmit;
00127         TransmittingAddrNum = -1;
00128         itr = 0;
00129         IsTransmitting = true;
00130         OnTransmitEnabled();
00131     }
00132 }
00133 
00134 void XbeeApi::OnTransmitEnabled(){
00135     if(IsTransmitting == true){
00136         if(NextTransmitIndex < BytesToTransmit){
00137             WriteWithEsc(buf[NextTransmitIndex]);
00138             NextTransmitIndex++;
00139         }else{
00140             NextTransmitIndex = 0;
00141             //次の送信先に切り替える
00142             while(true){
00143                 if(TransmittingAddrNum < 4){
00144                     TransmittingAddrNum++;
00145                     if(address[TransmittingAddrNum].IsAvailable == true){
00146                         //次の送信先に送るためのバッファの準備
00147                         for(int i = 0; i < 8; i++){
00148                             buf[i + 5] = address[TransmittingAddrNum].ADR[i];
00149                         }
00150                         buf[13] = address[TransmittingAddrNum].ADR16bit[0];
00151                         buf[14] = address[TransmittingAddrNum].ADR16bit[1];
00152                         buf[BytesToTransmit - 1] = (char)(0xFF - (CheckSum + address[TransmittingAddrNum].sum + address[TransmittingAddrNum].ADR16bit[0] + address[TransmittingAddrNum].ADR16bit[1]) & 0xFF);
00153                         Xbee.putc(buf[0]);
00154                         NextTransmitIndex++;
00155                         break;
00156                     }
00157                 }else{
00158                     //送信完了
00159                     IsTransmitting = false;
00160                     break;
00161                 }
00162             }
00163         }
00164     }
00165 }
00166 
00167 void XbeeApi::WriteWithEsc(char c){
00168     if(c == 0x7E){
00169         Xbee.putc(0x7D);
00170         Xbee.putc(0x5E);
00171     }else if(c == 0x7D){
00172         Xbee.putc(0x7D);
00173         Xbee.putc(0x5D);
00174     }else{
00175         Xbee.putc(c);
00176     }
00177 }
00178 
00179 void XbeeApi::ClearPacket(){
00180     CheckSum = 0;
00181     itr = 0;
00182 }
00183 
00184 
00185 //データ受信時の処理 1バイトごとに呼び出される必要がある
00186 void XbeeApi::OnDataReceived(){
00187     static bool EscFlag = false;
00188     static int PacketLength = 0;
00189     static bool IsReceivingPacket = false;
00190     
00191     char message;
00192     message = Xbee.getc();
00193     if(message == 0x7E){                    //パケットの先頭バイトは0x7E
00194         ReceivedBytesCounter = 0;
00195         PacketLength = 0;
00196         IsReceivingPacket = true;
00197         EscFlag = false;
00198     }
00199     if(IsReceivingPacket == true){
00200         if(message == 0x7D){
00201             EscFlag = true;
00202         }else{
00203             if(EscFlag == true){
00204                 RxBuf[ReceivedBytesCounter] = message ^ 0x20;
00205                 EscFlag = false;
00206             }else{
00207                 RxBuf[ReceivedBytesCounter] = message;
00208             }
00209             ReceivedBytesCounter++;
00210             if(ReceivedBytesCounter >= 256){
00211                 IsReceivingPacket = false;      //受信バッファを溢れる場合は、パケットの読み込みを中止する  次に0x7Eを受信するまで再開されない
00212             }
00213         }
00214         //この時点でReceivedBytesCounterには受信したデータのバイト数が入っている
00215         //2バイト目と3バイト目はパケットの長さを表している
00216         if(RxBuf[0] == 0x7E){
00217             if(ReceivedBytesCounter == 3){                      //パケットの3バイト目までを受信した時点で、パケットの長さを計算できる
00218                 PacketLength = 255 * RxBuf[1] + RxBuf[2];
00219             }
00220             if(ReceivedBytesCounter > 3 && ReceivedBytesCounter == PacketLength + 4){   //パケットの長さと同じだけのデータを受信したら
00221                 int sum = 0;
00222                 for(int i = 3; i < ReceivedBytesCounter - 1; i++){       //先頭3バイトとチェックサム以外のすべてのバイトを合計
00223                     sum += RxBuf[i];
00224                 }
00225                 if((char)(0xFF - sum & 0xFF) == RxBuf[ReceivedBytesCounter - 1]){   //チェックサムが一致するならば
00226                     //ここにデータ受信時の処理を書く
00227                     //パケット受信直後なので、多少時間のかかる処理でも問題ないはず
00228                     if(RxBuf[3] == 0x90){                                           // パケットタイプ0x90は他のXbeeから送信されたデータを表す
00229                         int DataLength = PacketLength - 12;                         //データ本体の長さは パケットの長さ - 12 ここでいう「パケットの長さ」に、最初の3バイトとチェックサムは含まない
00230                         OnPacketReceived(DataLength, &RxBuf[15]);                   //パケットタイプ0x90は地上局から送信されたデータが16バイト目 すなわち RxBuf[15] から格納されている
00231                         //OnPacketReceived(DataLength + 16, RxBuf);   //デバッグ用 パケットすべてを渡す場合
00232                         if(DataLength == 2 && RxBuf[15] == 0x59 && RxBuf[16] == 0x4D){      //0x594Dが送られて来たら、送信元の64bitアドレスをチェックする
00233                             for(int i = 0; i < 4; i++){
00234                                 bool IsMatchAddr = true;
00235                                 for(int j = 0; j < 8; j++){
00236                                     if(address[i].ADR[j] != RxBuf[j + 4]){
00237                                         IsMatchAddr = false;                                //16bitアドレスを調べる 1つでも一致しなければ終了するし
00238                                         break;
00239                                     }
00240                                 }
00241                                 if(IsMatchAddr == true){                                    //0x594Dを送信してきた地上局の64bitアドレスがaddress[i]と一致した場合
00242                                     address[i].ADR16bit[0] = RxBuf[12];                     //address[i]の16bitアドレスを地上局側に合わせる
00243                                     address[i].ADR16bit[1] = RxBuf[13];
00244                                     address[i].IsAvailable = true;
00245                                     break;
00246                                 }
00247                             }
00248                         }
00249                     }
00250                 }
00251                 IsReceivingPacket = false;
00252             }
00253         }
00254     }
00255 }
00256 
00257 void XbeeApi::SetInterrupt(bool val){
00258     if(val == true){
00259         Xbee.attach(callback(this, &XbeeApi::OnDataReceived), Serial::RxIrq);
00260         Xbee.attach(callback(this, &XbeeApi::OnTransmitEnabled), Serial::TxIrq);
00261     }else{
00262         Xbee.attach(NULL, Serial::RxIrq);
00263         Xbee.attach(NULL, Serial::TxIrq);
00264     }
00265 }
00266