XbeeApi
Dependents: XbeeAPI Hybrid_main_FirstEdtion
Diff: XbeeApiLib.cpp
- 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{ + } +} +