XbeeApi

Dependents:   XbeeAPI Hybrid_main_FirstEdtion

Revision:
0:bca23ad9e6b5
Child:
1:34007fc9235e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeApiLib.cpp	Fri Jan 20 08:13:54 2017 +0000
@@ -0,0 +1,270 @@
+#include "mbed.h"
+#include <XbeeApiLib.h>
+#include <string>
+
+XbeeApi::XbeeApi(PinName Tx, PinName Rx, int BaudRate) : Xbee(Tx, Rx, BaudRate){
+    //Xbee = Serial(Tx, Rx, BaudRate);
+    //Xbee.baud(BaudRate);
+    
+    HopLimit = 0;
+    for(int i = 0;i < 4;i++){
+        address[i].IsAvailable = false;
+    }
+    IsTransmitting = false;
+}
+
+void XbeeApi::SetAddress(int Num, unsigned long HIGH, unsigned long LOW){
+    for(int i = 0;i < 4;i++){
+        address[Num].ADR[3 - i] = reinterpret_cast<char (&)[sizeof(HIGH)]>(HIGH)[i];
+        address[Num].ADR[7 - i] = reinterpret_cast<char (&)[sizeof(LOW)]>(LOW)[i];
+    }
+    address[Num].IsAvailable = true;
+    address[Num].sum = 0;
+    //EndPacket()でチェックサムを計算する際、宛先アドレスもチェックサムに含まれる
+    //宛先アドレスは頻繁に変更されないので、アドレス分の合計だけを先にまとめて計算しておく
+    for(int i = 0;i < 8;i++){
+        address[Num].sum += address[Num].ADR[i];
+    }
+    address[Num].ADR16bit[0] = 0x00;
+    address[Num].ADR16bit[1] = 0x00;
+}
+
+//
+//char StartWith: 送信されるデータの最初の1バイトに送信内容のタグとしての役割を持たせている
+//これにより、受信側では送信されてきたバイナリデータをどのような形式で読み取ればよいのか判断する
+void XbeeApi::StartPacket(char StartWith){
+    CheckSum = 0x12;
+    buf[17] = StartWith;
+    itr = 18;
+}
+
+//文字列を送信バッファに書き込む
+void XbeeApi::Write(string val){
+    int length = val.length();
+    if(length < 128 - itr){     //送信バッファの空きよりも文字列が長い場合は何もしない
+        for(int i = 0;i < length;i++){
+            buf[itr + i] = val.c_str()[i];
+        }
+        itr += length;
+    }else{
+        buf[17] = 0x00;
+        EndPacket();
+    }
+}
+
+//int型の数値をバイト列として書き込む
+//リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
+void XbeeApi::Write(int val){
+    if(sizeof(val) < 128 - itr){
+        for(int i = 0;i < sizeof(val);i++){
+            buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
+        }
+        itr += sizeof(val);
+    }else{
+        buf[17] = 0x00;
+        EndPacket();
+    }
+}
+
+//double型の数値をバイト列として書き込む
+//リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
+void XbeeApi::Write(double val){
+    if(sizeof(val) < 128 - itr){
+        for(int i = 0;i < sizeof(val);i++){
+            buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
+        }
+        itr += sizeof(val);
+    }else{
+        buf[17] = 0x00;
+        EndPacket();
+    }
+}
+
+//float型の数値をバイト列として書き込む
+//リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
+void XbeeApi::Write(float val){
+    if(sizeof(val) < 128 - itr){
+        for(int i = 0;i < sizeof(val);i++){
+            buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
+        }
+        itr += sizeof(val);
+    }else{
+        buf[17] = 0x00;
+        EndPacket();
+    }
+}
+
+/*void XbeeApi::EndPacket(){
+    if(itr != 0){
+        CheckSum += 0x12;
+        for(int i = 0;i < itr;i++){
+            CheckSum += buf[i];
+        }
+        for(int i = 0; i < 4;i++){
+            if(address[i].IsAvailable == true){
+                Xbee.putc(0x7E);    //パケットの先頭を表す
+                WriteWithEsc((char)(itr + 14) >> 8);
+                WriteWithEsc((char)(itr + 14) & 0x00FF);
+                WriteWithEsc(0x10);
+                WriteWithEsc(0x00);         //ここを01にするとxbeeは送信の成否の判定を行うようになる(クソ重い)
+                //宛先アドレスを書き込む
+                for(int j = 0;j < 8;j++){
+                    WriteWithEsc(address[i].ADR[j]);
+                }
+                WriteWithEsc(address[i].ADR16bit[0]);
+                WriteWithEsc(address[i].ADR16bit[1]);
+                WriteWithEsc(0x01);
+                WriteWithEsc(0x01);
+                //データを書き込む
+                for(int j = 0;j < itr;j++){
+                    WriteWithEsc(buf[j]);
+                }
+                //チェックサムを書き込む
+                WriteWithEsc((char)(0xFF - (CheckSum + address[i].sum + address[i].ADR16bit[0] + address[i].ADR16bit[1]) & 0xFF));
+            }
+        }
+        CheckSum = 0;
+        itr = 0;
+    }
+}*/
+
+void XbeeApi::EndPacket(){
+    if(itr != 0){
+        buf[0] = 0x7E;    //パケットの先頭を表す
+        buf[1] = (char)(itr - 3) >> 8;
+        buf[2] = (char)(itr - 3) & 0x00FF;
+        buf[3] = 0x10;
+        buf[4] = 0x00;         //ここを01にするとxbeeは送信の成否の判定を行うようになる(クソ重い)
+        buf[15] = 0x01;
+        buf[16] = 0x01;         //0x01:送りっぱなし
+        for(int i = 17;i < itr; i++){
+            CheckSum += buf[i];
+        }
+        BytesToTransmit = itr + 1;
+        NextTransmitIndex = BytesToTransmit;
+        TransmittingAddrNum = -1;
+        itr = 0;
+        IsTransmitting = true;
+        OnTransmitEnabled();
+    }
+}
+
+void XbeeApi::OnTransmitEnabled(){
+    if(IsTransmitting == true){
+        if(NextTransmitIndex < BytesToTransmit){
+            WriteWithEsc(buf[NextTransmitIndex]);
+            NextTransmitIndex++;
+        }else{
+            NextTransmitIndex = 0;
+            //次の送信先に切り替える
+            while(true){
+                if(TransmittingAddrNum < 4){
+                    TransmittingAddrNum++;
+                    if(address[TransmittingAddrNum].IsAvailable == true){
+                        //次の送信先に送るためのバッファの準備
+                        for(int i = 0; i < 8; i++){
+                            buf[i + 5] = address[TransmittingAddrNum].ADR[i];
+                        }
+                        buf[13] = address[TransmittingAddrNum].ADR16bit[0];
+                        buf[14] = address[TransmittingAddrNum].ADR16bit[1];
+                        buf[BytesToTransmit - 1] = (char)(0xFF - (CheckSum + address[TransmittingAddrNum].sum + address[TransmittingAddrNum].ADR16bit[0] + address[TransmittingAddrNum].ADR16bit[1]) & 0xFF);
+                        Xbee.putc(buf[0]);
+                        NextTransmitIndex++;
+                        break;
+                    }
+                }else{
+                    //送信完了
+                    IsTransmitting = false;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+void XbeeApi::WriteWithEsc(char c){
+    if(c == 0x7E){
+        Xbee.putc(0x7D);
+        Xbee.putc(0x5E);
+    }else if(c == 0x7D){
+        Xbee.putc(0x7D);
+        Xbee.putc(0x5D);
+    }else{
+        Xbee.putc(c);
+    }
+}
+
+void XbeeApi::ClearPacket(){
+    CheckSum = 0;
+    itr = 0;
+}
+
+
+//データ受信時の処理 1バイトごとに呼び出される必要がある
+void XbeeApi::OnDataReceived(){
+    static DigitalOut LED(LED1);
+    static bool EscFlag = false;
+    static int PacketLength = 0;
+    static bool IsReceivingPacket = false;
+    
+    char message;
+    message = Xbee.getc();
+    if(message == 0x7E){                    //パケットの先頭バイトは0x7E
+        ReceivedBytesCounter = 0;
+        PacketLength = 0;
+        IsReceivingPacket = true;
+        EscFlag = false;
+    }
+    if(IsReceivingPacket == true){
+        if(message == 0x7D){
+            EscFlag = true;
+        }else{
+            if(EscFlag == true){
+                RxBuf[ReceivedBytesCounter] = message ^ 0x20;
+                EscFlag = false;
+            }else{
+                RxBuf[ReceivedBytesCounter] = message;
+            }
+            ReceivedBytesCounter++;
+        }
+        //この時点でReceivedBytesCounterには受信したデータのバイト数が入っている
+        //2バイト目と3バイト目はパケットの長さを表している
+        if(RxBuf[0] == 0x7E){
+            if(ReceivedBytesCounter == 3){
+                PacketLength = 255 * RxBuf[1] + RxBuf[2];
+            }
+            if(ReceivedBytesCounter > 3 && ReceivedBytesCounter == PacketLength + 4){
+                int sum = 0;
+                for(int i = 3; i < ReceivedBytesCounter - 1; i++){       //先頭3バイトとチェックサム以外のすべてのバイトを合計
+                    sum += RxBuf[i];
+                }
+                if((char)(0xFF - sum & 0xFF) == RxBuf[ReceivedBytesCounter - 1]){
+                    //ここにデータ受信時の処理を書く
+                    //パケット受信直後なので、多少時間のかかる処理でも問題ないはず
+                    if(RxBuf[3] == 0x90){
+                        int DataLength = PacketLength - 12;
+                        //パケットタイプ0x90は地上局から送信されたデータが16バイト目 すなわち RxBuf[15] から格納されている
+                        if(DataLength == 2 && RxBuf[15] == 0x59 && RxBuf[16] == 0x4D){
+                            LED = !LED;
+                            address[0].ADR16bit[0] = RxBuf[12];
+                            address[0].ADR16bit[1] = RxBuf[13];
+                        }
+                        if(DataLength == 2 && RxBuf[15] == 0x5E){
+                            
+                        }
+                    }
+                }
+                IsReceivingPacket = false;
+            }
+        }
+    }
+}
+
+void XbeeApi::SetInterrupt(bool val){
+    if(val == true){
+        Xbee.attach(callback(this, &XbeeApi::OnDataReceived), Serial::RxIrq);
+        Xbee.attach(callback(this, &XbeeApi::OnTransmitEnabled), Serial::TxIrq);
+    }else{
+    }
+}
+