シリアル通信パケット用のCOBSデコーダも作ってみる

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) COBSがふにおちたい　その２

#やること
前回記事[「シリアル通信パケット用のCOBSエンコーダーを作ってみる」](https://qiita.com/Ninagawa_Izumi/items/ef06007fe6ccb1720dd5)の続きです。
デコーダーを作ります。

前回記事：

https://qiita.com/Ninagawa_Izumi/items/ef06007fe6ccb1720dd5


#参考
https://qiita.com/hideakitai/items/347985528656be03b620

前回同様、こちらの記事を参考にさせていただきました。ありがとうございました。

# 使うもの
- Arduino
- Arduino IDE など


# 実装
COBSのデコーダーを作ります。
下記のスクリプトでは
・もとのデータを表示
・エンコードしたデータを表示
・それをデコードのためにトリミングしたデータを表示
・上記に0x00を入れて元のデータを復元したデコード結果を表示
という順に作業をしています。


```c++:Arduino
//1バイト型で作っているため、データ配列の最大長は254

//↓送信したいデータの配列。データを書き換えてテストできます。（uint8_t型の値のみ）
uint8_t source_data[] = {00, 00, 185, 00, 33, 00, 44, 00, 00, 55, 00, 00, 200, 222, 130, 566, 60, 00}; //適当な数字

uint8_t cobs[sizeof(source_data) + 2]; // COBSに変換した送信データの配列（上記に２バイト追加）
uint8_t received_data[sizeof(source_data)]; //受信後にデコードしたデータを入れる配列。

void setup() {
  Serial.begin(115200);//シリアルモニター表示
  delay(500);
}

void loop() {

  // **** 元のデータの表示 ****
  Serial.print("Source Data   :   ");
  for (int i = 0 ; i < sizeof(source_data) ; i++)
  {
    Serial.print(source_data[i]);
    Serial.print(",");
  }
  Serial.println();

  // **** 配列をCOBSの方式で処理する　エンコーダー ****

  uint8_t count = 0; //次にsource_data[i]に0x00が出るまでの配列番号をカウント
  int mark = 0; //最後に0x00が出たsource_data[i]の配列番号をキープ

  for (int i = 0 ; i < sizeof(source_data) + 1; i++) {

    //現在チェックしているsource_data[i]の中身が0x00ではない場合
    if (source_data[i] != 0x00) {
      cobs[i + 1] = source_data[i]; //チェックした値をそのままcobs配列に書き込む
      count ++;//前回0x00が出たsource_data[i]の配列内のカウント値を+1
    }

    //現在チェックしているsource_data[i]の中身が0x00だった場合
    else {
      count ++;//前回0x00が出た配列のカウントを+1
      cobs[mark] = count;//前回0x00が出たcobs配列にカウント値を書き込み確定
      mark = i + 1; // 現在のcobs配列を0x00が出た配列としてキープ
      count = 0 ;//0x00が出た配列のカウントをリセット
      cobs[mark] = count; //今回0x00が出たcobs配列にカウント値を書き込む
    }
  }

  //COBSの末端処理
  cobs[mark] = count; //前回0x00が出た配列にカウント値を改めて書き込む
  cobs[sizeof(source_data) + 1] = 0; //終端に0x00を代入する

  //エンコーダーで変換した結果を表示
  Serial.print("Encorded Data : ");
  for (int i = 0 ; i < sizeof(source_data) + 2; i++){
    Serial.print(cobs[i]); Serial.print(",");
  }
  Serial.println();

  // ** COBSから元のデータを復元するデコーダー **

  //先頭と末尾をトリムしたデータを作成する（0x00はまだ代入していない）
  for (int i = 0; i < sizeof(received_data); i++) { //全パケットをデコード結果用の配列に取り込む（先頭と末尾を除く）
    received_data[i] = cobs[i + 1];
  }

  //先頭と末尾をトリムしたデータの表示
  Serial.print("Trimmed Data  :   ");
  for (int i = 0 ; i < sizeof(received_data); i++) {
    Serial.print(received_data[i]); Serial.print(",");
  }
  Serial.println();

  //該当する場所に0x00を代入する処理
  int i = 0;
  while ( i <= sizeof(received_data)) {
    i = i + cobs[i];
    received_data[i - 1] = 0;
  }

  //0x00を代入したデコード結果の表示
  Serial.print("Decorded Data :   ");
  for (int i = 0; i < sizeof(received_data); i++) {
    Serial.print(received_data[i]); Serial.print(",");
  }
  Serial.println(); Serial.println();
  delay(1000);
}
```

#動作確認

デフォルトではシリアルモニタに下記のような結果を出力します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/cc0978bf-90fd-e282-560f-da267e8a37d1.png" width = 600>

Source Data  : 最初のデータ
Encorded Data: COBSにエンコードしたデータ
Trimmed  Data: デコード用にCOBSの先頭と末尾をトリミングしたデータ
Decorded Data: 0x00を代入して元のデータを再現したもの

source_data[]の中の配列データを書き換えたり要素数を増やしたりして挙動を確認できます。

# まちがっていたら
すみません！


# つぎやること
共用体を使って2バイトデータを格納、送信できるようにします。

前回記事：

https://qiita.com/Ninagawa_Izumi/items/ef06007fe6ccb1720dd5