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.
Dependents: XbeeAPI Hybrid_main_FirstEdtion
XbeeApiLib.cpp
- Committer:
- ark777
- Date:
- 2017-03-10
- Revision:
- 1:34007fc9235e
- Parent:
- 0:bca23ad9e6b5
- Child:
- 2:30220fb0e20e
File content as of revision 1:34007fc9235e:
#include "mbed.h"
#include <XbeeApiLib.h>
#include <string>
XbeeApi::XbeeApi(PinName Tx, PinName Rx, int BaudRate, void (*onPacketReceived)(int, char*)) : 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;
SetInterrupt(true);
OnPacketReceived = onPacketReceived;
}
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 = false;
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();
}
}
//long型の数値をバイト列として書き込む
//リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
void XbeeApi::Write(long long 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){
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 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++;
if(ReceivedBytesCounter >= 256){
IsReceivingPacket = false; //受信バッファを溢れる場合は、パケットの読み込みを中止する 次に0x7Eを受信するまで再開されない
}
}
//この時点でReceivedBytesCounterには受信したデータのバイト数が入っている
//2バイト目と3バイト目はパケットの長さを表している
if(RxBuf[0] == 0x7E){
if(ReceivedBytesCounter == 3){ //パケットの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){ // パケットタイプ0x90は他のXbeeから送信されたデータを表す
int DataLength = PacketLength - 12; //データ本体の長さは パケットの長さ - 12 ここでいう「パケットの長さ」に、最初の3バイトとチェックサムは含まない
OnPacketReceived(DataLength, &RxBuf[15]); //パケットタイプ0x90は地上局から送信されたデータが16バイト目 すなわち RxBuf[15] から格納されている
//OnPacketReceived(DataLength + 16, RxBuf); //デバッグ用 パケットすべてを渡す場合
if(DataLength == 2 && RxBuf[15] == 0x59 && RxBuf[16] == 0x4D){
address[0].ADR16bit[0] = RxBuf[12];
address[0].ADR16bit[1] = RxBuf[13];
address[0].IsAvailable = true;
}
}
}
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{
Xbee.attach(NULL, Serial::RxIrq);
Xbee.attach(NULL, Serial::TxIrq);
}
}