セクションの複数ページをまとめています。 印刷またはPDF形式で保存...

もとのページに戻る

2024-09-06 現在

入出力ストリーム

入出力ストリームを処理する上位クラス
入出力ストリームを処理する上位クラスです。
  • CRTP (Curiously Recurring Template Pattern) 手法を用いたポリモーフィズムにより、いくつかのクラス(Serial, Wire, SPI, smplbuf) にインタフェースを提供します。
    • CRTP では下位クラスは template class Derived : public stream<Derived>;のように定義し、上位クラスからも下位クラスのメソッドを参照します。
  • 本クラスでは print メソッド、<< 演算子などの共通処理の定義を行い、下位クラスで実装した write() メソッドなどを呼び出すことで、仮想関数を用いるのと近い実装を行っています。

インタフェース(下位クラスで実装)

下位クラスでは、以下に列挙する関数を実装します。

available()

int available()

// example
while(Serial.available()) {
  int c = Serial.read();
  // ... any
}

入力が存在する場合は 1、存在しない場合は 0 を返します。

パラメータ解説
戻り値 int0: データなし 1:データあり

flush()

void flush()

// example
Serial.println("long long word .... ");
Serial.flush();

出力をフラッシュ(出力完了まで待つ)します。

read()

int read()

// example
int c;
while (-1 != (c = read())) {
    // any
}

ストリームより1バイトデータを入力します。データが存在しない場合は -1 を戻します。

write()

size_t write(int c)

// example
Serial.write(0x30);

ストリームに1バイト出力します。

パラメータ解説
n出力したい文字。
戻り値 size_t出力が成功すれば 1、失敗すれば 0。

vOutput()

static void vOutput(char out, void* vp)

1バイト出力を行うスタティック関数です。クラスメソッドではないため、メンバー変数等の情報は利用できません。替わりにパラメータとして渡される vp にクラスインスタンスへのポインタを渡します。

このスタティック関数は内部的に利用されfctprintf()の1バイト出力関数として関数ポインタが渡ります。これを用いてprintメソッドなどを実装しています。

パラメータ解説
out出力したい文字
vpクラスインスタンスへのポインタ
通常は、元のクラスにキャストして write() メソッドを呼び出す

インタフェース

putchar()

void mwx::stream::putchar(char c)

// example
Serial.putchar('A');
// result -> A

1バイト出力します。

size_t print(T val, int base = DEC) // T: 整数型
size_t print(double val, int place = 2)
size_t print(const char*str)
size_t print(std::initializer_list<int>)

// example
Serial.print("the value is ");
Serial.print(123, DEC);
Serial.println(".");
// result -> the value is 123.

Serial.print(123.456, 1);
// result -> 123.5

Serial.print({ 0x12, 0x34, 0xab, 0xcd });
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

各種整形出力を行います。

パラメータ解説
val整形出力したい数値型
base出力形式BIN 二進数 / OCT 8進数 / DEC 10進数 / HEX 16進数
place小数点以下の桁数
戻り値 size_t書き出したバイト数

printfmt()

size_t printfmt(const char* format, ...);

// example
Serial.printfmt("the value is %d.", 123);
// result -> the value is 123.

printf 形式での出力を行います。

TWESDK/TWENET/current/src/printf/README.md 参照

operator <<

// examples
Serial << "this value is" // const char*
       << int(123)
       << '.';
       << mwx::crlf;
// result -> this value is 123.

Serial << fromat("this value is %d.", 123) << twe::crlf;
// result -> this value is 123.

Serial << mwx::flush; // flush here

Serial << bigendian(0x1234abcd);
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

Serial << int(0x30) // output 0x30=48, "48"
       << '/'
       << uint8_t(0x31); // output '1', not "48"
// result -> 48/1

smplbuf<char,16> buf = { 0x12, 0x34, 0xab, 0xcd };
Serail << but.to_stream();
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

Seiral << make_pair(buf.begin(), buf.end());
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

Serial << bytelist({ 0x12, 0x34, 0xab, 0xcd });
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.
引数型解説
char1バイト出力 (数値としてフォーマットはしない)
int整数出力 (printf の “%d”)
double数値出力 (printf の “%.2f”)
uint8_t1バイト出力する(char型と同様)
uint16_t2バイト出力する(ビッグエンディアン順)
uint32_t4バイト出力する(ビッグエンディアン順)
const char*``uint8_t*``const char[S]終端文字までを出力します。出力には終端文字は含まれません。(Sは固定配列のサイズ指定)
uint8_t[S]配列サイズSバイト分をそのまま出力します。(Sは固定配列のサイズ指定)
format()printf 形式での出力
mwx::crlf改行 CRLF の出力
mwx::flush出力のフラッシュ
bigendian()数値型をビッグエンディアン順で出力する。(右辺値)
std::pair<T*, T*>バイト型の begin(), end() ポインタを格納したペア。make_pair により生成できる。Tuint8_t 型を想定する。(右辺値)
bytelist()std::initializer_list を用いるバイト列の出力
smplbuf<uint8_t,AL>&uint8_t型の配列クラスの内容を出力する。ALCメモリ確保手段
smplbuf<uint8_t, AL>::to_stream()smplbuf&#x3C;T> のデータを出力する
Tuint8_t型、ALメモリ確保手段

set_timeout(), get_error_status(), clear_error_status()

uint8_t get_error_status()
void clear_error_status()
void set_timeout(uint8_t centisec)

// example
Serial.set_timeout(100); // 1000msのタイムアウトを設定
uint8_t c;
Serial >> c;

>>演算子を用いた入力タイムアウトとエラーを管理します。

set_timeout() によりタイムアウト時間を指定し、>>演算子により入力処理を行います。所定時間内までに入力が得られない場合は get_error_status() によりエラー値を読み出せます。clear_error_status()によりエラー状況をクリアします。

引数型解説
centisec1/10秒単位でタイムアウト時間を設定します。0xffを指定した場合は、タイムアウトを無効とします。

エラー値

意味
0エラーなし
1エラー状況

operator >>

inline D& operator >> (uint8_t& v)
inline D& operator >> (char_t& v)
template <int S> inline D& operator >> (uint8_t(&v)[S])
inline D& operator >> (uint16_t& v)
inline D& operator >> (uint32_t& v)
inline D& operator >> (mwx::null_stream&& p)

//// 例
uint8_t c;

the_twelite.stop_watchdog(); // ウォッチドッグの停止
Serial.set_timeout(0xFF); // タイムアウト無し

// 1バイト読み出す
Serial >> c;
Serial << crlf << "char #1: [" << c << ']';

// 読み捨てる
Serial >> null_stream(3); // 3バイト分読み捨てる
Serial << crlf << "char #2-4: skipped";

// 4バイト分読み出す (uint8_t 型固定長配列限定)
uint8_t buff[4];
Serial >> buff;
Serial << crlf << "char #5-8: [" << buff << "]";

入力処理を行います。

以下に読み出し格納できる型を列挙します。

引数型解説
uint8_t, char_t1バイト入力
uint16_t2バイト入力(ビッグエンディアン順)
uint32_t4バイト入力(ビッグエンディアン順)
uint8_t[S]Sバイト分入力(Sは固定配列のサイズ指定)
null_stream(int n)nバイト読み捨てる

1 - mwx::mwx_format

printf の書式入力
mwx::stream の « 演算子に対してフォーマット書式を書き出すヘルパークラスです。

ライブラリ内では Using format=mwx::mwx_format; として別名定義しています。

Serial << format("formatted print: %.2f", (double)3123 / 100.) << mwx::crlf;

// formatted print: 31.23[改行]
  • コンストラクタで受け取った引数リストを、パラメータパックの展開機能を用いてクラス内部変数に格納する
  • operator << が呼び出された時点で、fctprintf() を呼び出し、ストリームにデータを書き出す

コンストラクタ

format(const char *fmt, ...)

コンストラクタでは、書式のポインタとパラメータを保存します。続く <<演算子による呼び出しでフォーマットを解釈して出力処理を行います。

パラメータ解説
fmtフォーマット書式。TWESDK/TWENET/current/src/printf/README.md 参照
...フォーマット書式に応じたパラメータ。
※ 最大数は4で、5つ以上のパラメータではコンパイルエラーとなる。※ 書式との整合性はチェックしないため、不整合な入力に対しては安全ではない。

2 - mwx::bigendian

ビッグエンディアン順のデータ出力
mwx::stream<< 演算子に対して数値型をビッグエンディアンのバイト列で出力するヘルパークラスです。
Serial << mwx::bigendian(0x1234abcdUL);

// output binary -> 0x12 0x34 0xab 0xcd

コンストラクタ

template <typename T>
bigendian::bigendian(T v)
パラメータ解説
vuint16_t または uint32_t の型の値

3 - mwx::crlf

改行コード出力
mwx::stream<< 演算子に対して改行コード (CR LF) を出力するためのヘルパークラスのインスタンスです。
Serial << "hello world!" << mwx::crlf;

4 - mwx::flush

出力バッファ強制出力
mwx::stream の出力バッファをフラッシュします。

flush() メソッドを呼び出すヘルパークラスへのインスタンスです。

for (int i = 0; i < 127; ++i) {
    Serial << "hello world! (" << i << ")" << twe::endl << twe::flush;
}
  • シリアルポートの場合は出力完了までポーリング待ちを行う
  • mwx::simpbuf バッファの場合は 0x00 を末尾に出力する(サイズは変更しない)

5 - stream_helper

ヘルパーオブジェクト
stream_helperは、mwx::streamインタフェースを付与するヘルパーオブジェクトです。データクラスを参照するヘルパーオブジェクトを生成し、ヘルパーオブジェクト経由でデータの入出力を行います。

以下にはsmplbufの配列bからヘルパーオブジェクトbsを生成しmwx::stream::operator <<()演算子によるデータ入力を行っています。

smplbuf_u8<32> b;
auto&& bs = b.get_stream_helper(); // ヘルパーオブジェクト

// データ列の生成
uint8_t FOURCHARS[]={'A', 'B', 'C', 'D'};
bs << FOURCHARS;
bs << ';';
bs << uint32_t(0x30313233); // "0123"
bs << format(";%d", 99);

Serial << b << crlf; // Serialへの出力は smplbuf_u8<32> クラス経由で

//結果: ABCD;0123;99

概要

stream_helper はデータ配列をストリームに見立てて振舞います。

内部にはデータ配列中の読み書き位置を保持しています。次のようにふるまいます。

  • 読み出しまたは書き込みをすると次の読み書き位置に移動します。
  • 最期のデータを読み出した後、またはデータを末尾に追記した後には、読み書き位置は終端となります。
  • 読み書き位置が終端の場合、
    • available()falseになります。
    • 読み出しは出来ません。
    • 書き込みは書き込み可能範囲であれば追記します。

stream_helperの生成

stream_helper は、データクラス (smplbuf, EEPROM) のメンバー関数より生成します。

auto&& obj_helper = obj.get_stream_helper()
// obj はデータクラスのオブジェクト、obj_helperの型は長くなるのでauto&&で受けています。

メソッド

rewind()

void rewind()

読み書き位置を先頭に移動します。

seek()

int seek(int offset, int whence = MWX_SEEK_SET)

読み書き位置を設定します。

whence設定位置
MWX_SEEK_SET先頭位置から設定します。offset0を指定するとrewind()と同じ意味になります。
MWX_SEEK_CUR現在位置を基準にoffset分移動しまします。
MWX_SEEK_END終端位置にします。offset0にすると終端に設定します。-1を設定すると最後の文字に移動します。

tell()

int tell()

読み書き位置を返します。終端位置の場合は-1を返します。

available()

int available()

読み書き位置が終端であれば0を返します。終端でなければそれ以外の値を返します。