yosuke kitajima / BusSerial

Dependencies:   BufferedSerial

Dependents:   FourOmniMecha

BusSerial.cpp

Committer:
ttrist
Date:
2020-11-11
Revision:
4:3b347fa779b7
Parent:
2:6895c7ec9db1
Child:
6:496eaf58c584

File content as of revision 4:3b347fa779b7:

#include "BusSerial.h"

BusSerial::BusSerial(PinName tx, PinName rx,Timer *timer):BufferedSerial(tx,rx)
{
    _timer = timer;
    _timer -> start();
}


// ヘッダー照合のみの超単純な受信関数.
// 引数は(格納先配列アドレス, ヘッダー番号, データ数)
// データ数はヘッダーの後ろに続く使用するデータの個数.
// ex)255 1 0 20 72 と送信されるなら 4(個)である.
//    この表現 vs 格納先配列の要素数 どちらが使いやすくなるのか?それによって今後変えるかも
// 戻り値として,通信が正常にできたらtrueを返す.
bool BusSerial::getBusSerial(uint8_t* container, uint8_t head_num, uint8_t data_quantity)
{
    //格納先配列の初期化
    for (uint8_t i = 0; i < data_quantity + 1; i++) container[i] = 0;

    // データ格納.ヘッダーがくるまで受信し続ける
    while (container[0] != head_num)
        if (readable() > 0) container[0] = getc();

    // 通信の中身を受信
    for (uint8_t i = 1; i < data_quantity + 1; i++) {
        if (readable() > 0) container[i] = getc();
        else                i--; // 受信できない状態なら次も同じiの値で処理
    }

    // 受信バッファに溜まったデータをクリア.いらないかも.
    deleteBufferData();

    // 受信データを正常に取得できたか?
    if(container[0] == head_num) return true;
    else                         return false;
}


// ヘッダー照合とタイムアウト処理できる受信関数.
// 引数は(格納先配列アドレス, ヘッダー番号, データ数, タイムアウト時間ms)
// タイムアウトはこの関数が呼ばれてから~ms後にfalseを返す
bool BusSerial::getTimedBusSerial(uint8_t* container, uint8_t head_num, uint8_t data_quantity, int timeout)
{
    // 受信開始時間記録
    int time_start = _timer->read_ms();

    for (uint8_t i = 0; i < data_quantity + 1; i++) container[i] = 0;
    while (container[0] != head_num) {
        if (readable() > 0)                           container[0] = getc();
        if (_timer->read_ms() - time_start > timeout) return false;
    }

    for (uint8_t i = 1; i < data_quantity + 1; i++) {
        if (readable() > 0) container[i] = getc();
        else                {
            i--;
            if (_timer->read_ms() - time_start > timeout) return false;
        }
    }

    deleteBufferData();

    if(container[0] == head_num) return true;
    else                         return false;
}


// ヘッダーとフッター照合の受信関数.
// 引数は(格納先配列アドレス, ヘッダー番号, データ数, フッター番号)
bool BusSerial::getBusSerial(uint8_t* container, uint8_t head_num, uint8_t data_quantity, uint8_t footer_num)
{
    // フッター分が追加されるため +2 となる.
    for (uint8_t i = 0; i < data_quantity + 2; i++) container[i] = 0;

    while (container[0] != head_num)
        if (readable() > 0) container[0] = getc();
    for (uint8_t i = 1; i < data_quantity + 2; i++) {
        if (readable() > 0) container[i] = getc();
        else                i--;
    }

    if(container[0] == head_num && container[data_quantity + 1] == footer_num) return true;
    else            return false;
}


// ヘッダーとフッター照合とタイムアウト処理できる受信関数.
// 引数は(格納先配列アドレス, ヘッダー番号, データ数, フッター番号, タイムアウト時間ms)
// タイムアウトはこの関数が呼ばれてから~ms後にfalseを返す
bool BusSerial::getTimedBusSerial
(uint8_t* container, uint8_t head_num, uint8_t data_quantity, uint8_t footer_num, int timeout)
{
    int time_start = _timer->read_ms();

    for (uint8_t i = 0; i < data_quantity + 2; i++) container[i] = 0;
    while (container[0] != head_num) {
        if (readable() > 0)                           container[0] = getc();
        if (_timer->read_ms() - time_start > timeout) return false;
    }

    for (uint8_t i = 1; i < data_quantity + 2; i++) {
        if (readable() > 0) container[i] = getc();
        else {
            i--;
            if (_timer->read_ms() - time_start > timeout) return false;
        }
    }
    deleteBufferData();
    if(container[0] == head_num && container[data_quantity + 1] == footer_num) return true;
    else                         return false;
}


// 配列のデータ送信.
// 正直中身をそのまま書いた方が楽.
void BusSerial::sendBusSerial(uint8_t *send_array, uint8_t size)
{
    for(uint8_t i = 0; i<size; i++) putc(send_array[i]);
}


// バッファ中身を全部読んで消去する.
void BusSerial::deleteBufferData()
{
    while (readable() > 0) getc();
}


// 旧式の通信関数.古いプロジェクト用に残す.
void BusSerial::GetBusSerial(uint8_t *Argument_Array, int myHead_ID, int RecieveData_sizeof, int BusSerialTimeout)
{
    long BusSerialTimeout_start_t = _timer->read_ms();  //タイマーセット
    for (int i = 0; i <  RecieveData_sizeof; i++) *(Argument_Array + i) = 0; //データ初期化

    //*** データ受信 ちゃんとなるまでループ(timeoutあり)***
    while (*Argument_Array != myHead_ID) {
        //*** 1byte読み込み ***
        if (readable() > 0) *Argument_Array = getc();

        if (*Argument_Array == myHead_ID ) {
            int old_i = 0;
            //*** データ格納エリア ***
            for (int i = 1; i <  RecieveData_sizeof; i++) {
                //格納中のtimeout処理用時間設定
                if (old_i != i) {
                    old_i = i;
                    BusSerialTimeout_start_t = _timer->read_ms(); //データ格納timeout用
                }

                //***データ格納部***
                if (readable() > 0) {
                    *(Argument_Array + i) = getc();
                } else {
                    if (_timer->read_ms() - BusSerialTimeout_start_t > BusSerialTimeout) break;
                    i--;
                }
            }
        }
        if (_timer->read_ms() - BusSerialTimeout_start_t > BusSerialTimeout) break;//timeout
    }
}