Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
pktparser(parser_packet)は、serparserで変換したバイト列に対して、内容の解釈を行います。
上記の例は、標準アプリケーションの0x81メッセージの解釈を行っています。parser_serオブジェクトによりSerialより入力された電文をバイト列に変換します。このバイト列をまずidentify_packet_type()
により電文の種別E_PKT
を特定します。電文の種別が判定できたら次に.parse<TwePacketTwelite>()
により電文を解析します。解析結果はTwePacketTwelite
型になりますが、このオブジェクトを取り出す手続きが.use<TwePacketTwelite>()
です。TwePacketTwelite
型はクラスですが構造体として直接メンバー変数を参照します。
バイト列を解析します。
T
には解析対象のパケット型を指定します。例えば標準アプリケーションの0x81メッセージならTwePacketTwelite
を指定します。
p
とe
はバイト列の先頭と終端の次を指定します。
戻り値はE_PKT
型です。エラーの場合はE_PKT::PKT_ERROR
が戻ります。
解釈したバイト列に対応するパケット型に対応するオブジェクトの参照を返します。事前にparse<T>を実行しエラーがなかった場合に呼び出すせます。
T
はparse<T>
で実行した型と同じもの、または基本的な情報のみ取得できるTwePacket
を指定します。
TwePacketPal
クラスは、TWELITE PALのパケットデータを解釈したものです。このクラスはTWELITE PAL(センサーデータなど上り方向)共通に取り扱います。
PAL共通データはDataPal
に定義されています。
PALの各センサー基板特有のデータを取り出すためのジェネレータ関数を用意しています。
PALは接続されるセンサーなどによってパケットデータ構造が異なりますが、DataPal
では共通部のデータ構造を保持します。
PALのパケットデータ構造は大まかに2つのブロックからなり、全てのPAL共通部と個別のデータ部になります。個別のデータ部は、パケットの解釈を行わずそのまま格納しています。取り扱いを単純化するため32バイトを超えるデータは動的に確保するuptr_snsdata
に格納します。
個別のデータ部は、PalBase
をベースクラスに持つ構造体に格納されます。この構造体は、TwePacketPal
に定義されるジェネレータ関数により生成されます。
parse<TwePacketPAL>()
実行時にMWX_PARSER_PKT_APPPAL_FIXED_BUF
に収まるサイズであれば、センサー個別のオブジェクトを生成します。
収まらない場合はau8snsdata
に解析時のバイト列の参照が保存されます。この場合、解析に用いたバイト列のデータが書き換えられた場合は、センサー個別のオブジェクトは生成できなくなります。
PALの各センサーのデータ構造体はすべてPalBase
を継承します。センサーデータの格納状況u32StoredMask
が含まれます。
PALイベントは、センサーなどの情報を直接送るのではなく、センサー情報を加工し一定の条件が成立したときに送信される情報です。例えば加速度センサーの静止状態から一定以上の加速度が検出された場合などです。
イベントデータが存在する場合はTwePacketPal
の.is_PalEvent()
がtrue
になることで判定でき、.get_PalEvent()
によりPalEvent
データ構造を得られます。
センサーPALの各種データを取り出すためのジェネレータ関数です。
ジェネレータ関数を利用するには、まずpkt
がイベントかどうか判定(.is_PalEvent()
)します。イベントの場合はget_PalEvent()
を持ちます。それ以外はu8palpcb
に応じてオブジェクトを生成します。
.u8palpcb==E_PAL_PCB::MAG
の場合、開閉センサーパルのデータPalMag
を取り出します。
.u8palpcb==E_PAL_PCB::AMB
の場合、環境センサーパルのデータPalAmb
を取り出します。
.u8palpcb==E_PAL_PCB::MOT
の場合、動作センサーパルのデータPalMot
を取り出します。
.is_PalEvent()
がtrue
の場合PalEvent
(PALイベント)を取り出します。
3軸の加速度センサーの値を格納するための構造体ですが、コンテナクラスに格納したときの利便性を上げるための手続きを追加しています。
axis_xyzt
を格納したコンテナクラスのイテレータをパラメータとして、X, Y, Z 軸のいずれかの要素にアクセスするイテレータを生成します。
以下の例では、buf.begin()
, buf.end()
をX軸用のイテレータとしてアルゴリズムstd::minmax_element
に用いています。
axis_xyzt
を格納したコンテナクラスのXYZ軸のいずれかの軸を取り出した仮想的なコンテナクラスを生成する関数です。この生成したクラスにはbegin()
とend()
メソッドのみ実装されています。このbegin()
とend()
メソッドで取得できるイテレータは前節get_axis_{x,y,z}_iter()のイテレータと同じものになります。
コンテナクラス(smplbuf
, smplque
)のテンプレート引数として指定し、内部で利用するメモリの確保または領域指定します。
このクラスはユーザコードから直接呼び出すものではありませんが、内部的にコンテナの宣言に用いられています。
alloc_attach
やalloc_heap
ではメモリ確保クラスに応じた初期化メソッド (init_???()
)を実行する必要があります。
バッファーp
・サイズn
で初期化します。
バッファのサイズを返す。
想定したallocクラスと違うメソッド呼び出し記述に対して、static_assert
のように、コンパイルエラーを発生させるためのメソッドです。
パケット種別定義
以下のパケットに対応します。
App_Wings の親機で出力されるアスキー書式に対応します。
このクラスはTWENETのtsRxDataApp
構造体のラッパークラスです。
このクラスオブジェクトは、ビヘイビアのコールバック関数またはthe_twelite.receiver.read()
により取得できます。
packet_rx
では、特にパケットのデータペイロードをsmplbuf
コンテナで取り扱えるようにし、expand_bytes()
などのユーティリティ関数によりペイロードの解釈記述を簡素化しています。
現時点では、シンプル中継ネットワーク<NWK_SIMPLE>
で必要とされるものを中心にメソッド等のインタフェースを実装しています。
パケットのデータペイロードを取得する。
<NWK_SIMPLE>
を用いた場合は、先頭に<NWK_SIMPLE>
用のヘッダデータがあります。戻りとして参照されるコンテナは、このヘッダ部分を除いた部分配列になります。ヘッダ部分まで参照したいときはget_psRxDataApp()
によりtsRxDataApp
構造体を参照してください。
TWENET Cライブラリの受信構造体を得る。
ペイロードのデータ長を返す。.get_payload().size()
と同じ値になる。
LQI値 (Link Quality Indicator)を得る。
LQIとは電波通信品質を示す値です。0から255までの数値で表されます。
ちなみに、いくつかの段階で評価する場合は、50未満(悪い -80dbm 未満)、50~100(やや悪い)、100~150(良好)、150以上(アンテナの近傍)といった区分けも可能です。これらは目安である点にご留意ください。
送信元のアドレスを得る。
get_addr_src_long()
は送信元のシリアル番号で、MSB(bit31)が必ず1になります。
get_addr_src_lid()
は送信元の論理IDで0x00
-0xFE
までの値をとります(<NWK_SIMPLE>
で指定する論理IDです)。
宛先アドレスを得ます。
宛先アドレスは、送信元で指定され、宛先の種別によって値の範囲が変わります。
暗号化パケットの場合は true
を返し、平文の時はfalse
を返します。
このクラスはTWENET CライブラリのtsTxDataApp
構造体のラッパクラスで、このクラスをベースとした派生クラスのオブジェクトをネットワークビヘイビアより取得して利用します。
ネットワークビヘイビアの .prepare_tx_packet()
によって行います。
上記の例ではthe_twelite.network.use<NWK_SIMPLE>()
によってネットワークビヘイビアのオブジェクトを取り出します。このオブジェクトの.prepare_tx_packet()
によってオブジェクトpkt
が生成されます。型名はauto&&で推論されていますがpacket_tx
の派生クラスになります。
このpkt
オブジェクトは、まず、()
内の条件判定にてtrue
かfalse
を返します。false
が返ってくるのは、送信用のキューが一杯でこれ以上要求が追加できない時です。
無線パケットには宛先情報など相手に届けるための様々な設定を行います。設定には設定内容を含むオブジェクトを<<演算子の右辺値に与えます。
以下に設定に用いるオブジェクトについて記載します。
各設定の利用可否や意味合いは、ネットワーク ビヘイビアの仕様によります。
宛先アドレスaddr
を指定します。宛先アドレスの値については、ネットワークビヘイビアの仕様を参照してください。
再送回数の指定を行います。再送回数はu8countで指定します。force_retryは、送信が成功しようがしまいが、指定回数の再送を行う設定です。
パケットを送信するまでの遅延と再送間隔を設定します。u16DelayMin
とu16DelayMax
の2つの値をミリ秒[ms]で指定します。送信要求をしてからこの間のどこかのタイミングで送信を開始します。再送間隔をu16RetryDur
の値[ms]で指定します。再送間隔は一定です。
内部処理の都合で指定通りのタイミングで送信処理が始まらない場合もあります。また、IEEE802.15.4の処理でもパケット創出までの時間ブレが発生します。これらのタイミングのブレは、多くのシステムではパケットの衝突回避を行う上で有効な手立てとなります。
厳格なタイミングでのパケット送信は、IEEE802.15.4の規格の性質上、例外的な使用方法とお考え下さい。
パケット送信を「できるだけ速やかに」実行するように要求する設定です。TWENETでのパケット送信処理は、1msごとに動作するTickTimer起点で行われています。この設定をすることで、要求後速やかにパケット送信要求が処理されます。もちろん、tx_packet_delay(0,0,0)
以外の設定では意味がない指定になります。
他のパケット送信処理が行われている場合は、通常の処理になります。
無線パケット通信では、送信完了後、送信相手先からACK(アック)という短い無線電文を得て、送信成功とする送信方法があります。このオプションを設定することで、ACK付き送信を行います。
ブロードキャストの指定を行います。
0..7の指定ができるTWENET無線パケットのタイプIDを指定します。
シリアル書式入出力 (mwx::serial_parser)
シリアル書式の入出力のために用います。内部に解釈済みのバイナリ系列を保持するバッファを持ち、入力時は1バイトずつ系列を読み出し書式に従い内部バッファに格納し、系列の解釈が完了した時点で完了状態になるものです。反対に出力時は内部バッファから所定の出力書式に従いバッファを出力します。
begin()
の初期化のパラメータで渡す書式の種別です。ここではアスキー形式とバイナリー形式の2種類があります。
バイナリ形式の取り扱いはアスキー形式に比べ、必要なツールや確認方法を含め一般に取り扱いが煩雑になります。通常はアスキー形式をお使いください。
アスキー形式は、バイナリで構成されたデータ列を文字列で表現する方法です。
例えばバイト列で 00A01301FF123456
をアスキー形式で表現すると、以下のようになります。先頭は :
で B1
がチェックサム、終端は [CR:0x0d][LF:0x0a]
となります。
:00A01301FF123456B1[CR][LF]
終端のチェックサムを省略できます。チェックサムからCRLFの系列をX
に置き換えます。文字化けによる誤ったデータ系列には弱くなりますが、実験などでデータを送付したいときに便利です。
:00A01301FF123456X
通常はアスキー形式を利用してください。
マイコン間通信での実装を考えるとバイナリ形式のほうが効率的ですが、実験などでの送受信の確認にはバイナリ通信に対応した特別なターミナルなどを準備する必要があり、チェックサムの計算も必須です。アスキー形式より利用の難易度は高くなります。
バイナリ形式は、バイナリで構成されたデータ列にヘッダとチェックサムを付加して送付する方法です。
例えば 00A01301FF123456
をバイナリ形式で表現すると、以下のようになります。
0xA5 0x5A 0x80 0x08 0x00 0xA0 0x13 0x01 0xFF 0x12 0x34 0x56 0x3D
宣言にはメモリの確保クラスを指定します。この指定は煩雑であるため、上述のように別名定義を行っています。
メモリ確保クラスに応じたbegin()
メソッドを呼び出します。
この定義は、特に、データ列を書式出力したい場合に用います(>>
演算子参照)
一度確保したヒープ領域は解放できません。
内部バッファを返す。バッファは smplbuf<uint8_t, alloc>
型となります。
入力文字を処理する。書式入力の入力文字列を1バイト受け取り書式に従い解釈します。例えばASCII書式では:00112233X
のような系列を入力として受け取りますが : 0 0 ... X
の順で1バイトずつ入力し、最後の X
を入力した時点で書式の解釈を完了し、完了済みと報告します。
parse()
のパラメータは入力バイト、戻り値は解釈完了であればtrue
を戻します。
parse()
で読み出し完了になったとき、次のparse()
を実行すると読み出し中のステータスに戻ります。
true
ならparse()
により読み出しが完了した状態で、false
なら解釈中となります。
内部バッファを書式形式でストリーム(Serial)に対して出力します。
特定のパケットであると解釈できなかった場合はE_PKT::PKT_ERROR
が戻ります。
TwePacketAppUart
クラスは、App_UARTの拡張書式を親機・中継器アプリApp_Wingsで受信したときの形式です。
パケットデータ内の諸情報はparse<TwePacketUART>()
実行後にDataAppUART
に格納されます。
簡易形式は解釈できません。parse<TwePacketUART>()
ではE_PKT::PKT_ERROR
を戻します。内容を確認するには元のバイト列を直接参照してください。
payload
はデータ部分ですが、マクロ定義によってデータ格納の方法が変わります。
MWX_PARSER_PKT_APPUART_FIXED_BUF
の値が0
としてコンパイルした場合は、payload
はパケット解析を行うバイト列を直接参照します。元のバイト列の値が変更されるとpayload
中のデータは破壊されます。
MWX_PARSER_PKT_APPUART_FIXED_BUF
の値を0
より大きい値として定義した場合は、payload
にはその値(バイト数)のバッファが確保されます。ただしシリアル電文のデータがバッファサイズを超えた場合はparse<TwePacketAppUART>()
は失敗しE_PKT::PKT_ERROR
を戻します。
パケット型の基底クラスですが、メンバー構造体common
にはアドレス情報など共通情報が含まれます。
種別を混在してpktparser型として配列等に格納するような場合に、アドレス情報などを最小限の情報を取得したい場合に使用します。
内部が配列構造のコンテナクラスです。初期化時にバッファの最大サイズを決定しますが、その最大サイズまでの範囲で可変長の配列として振る舞います。
オブジェクトの宣言例です。宣言の直後に初期化用のメソッド呼び出しを行います。いずれも初期化直後の最大サイズは128バイトで、サイズは0です。必要に応じてサイズを拡張しながら使用します。
上記のuint8_t
型に限り別名定義があります。
通常の配列のように[]演算子などを用いて要素にアクセスできますし、イテレータを用いたアクセスも可能です。
push_back()
メソッドを定義しています。末尾にデータを追記するタイプのアルゴリズムが使用可能になります。
型T
でサイズN
のコンテナを宣言します。宣言後に初期化のメソッドを呼び出します。
smplbuf_local
は、内部に固定配列により領域を確保します。コンストラクタによる初期化も可能です。
smplbuf_attach
では、使用するバッファの先頭ポインタT* buf
と配列の初期サイズsize
と最大サイズN
を指定します。コンストラクタによる初期化も可能です。
smplbuf_heap
は、HEAP領域(解放は不可能だが随時確保可能なメモリ領域)にメモリを確保します。一度確保したら開放できない領域ですので通常はグローバル領域に定義します。領域確保はinit_heap()
で行います。コンストラクタによるメモリ確保はできません。必ずinit_heap()
を呼び出して利用してください。
グローバルオブジェクトを生成する場合は、コンストラクタによる初期化が行なえません。実行初期(setup()
を推奨)に初期化関数init_local()
,attach()
,init_heap()
を呼び出すようにしてください。
初期化子リスト(イニシャライザリスト){ ... }
によるメンバーの初期化をできます。smplbuf_local
のローカル宣言でのコンストラクタでの利用を除き、初期化のメソッドを呼び出した後に有効です。
代入演算子の右辺値 (smplbuf_local
, smplbuf_attach
, smplbuf_heap
)
コンストラクタ(smplbuf_local
のローカル宣言、グローバル宣言は不可)
末尾にメンバーc
を追加します。append()
の戻り値はbool
で、バッファが一杯で追加できないときにfalse
が返ります。
pop_back()
は末尾のエントリを抹消します。ただしエントリのクリアはしません。
empty()
は配列に要素が格納されていない場合にtrue
を戻します。is_end()
は反対に配列サイズ一杯まで要素が格納されているときにtrue
を戻します。
size()
は配列の要素数を返します。
capacity()
は配列の最大格納数を返します。
reserve()
は配列のサイズを拡張します。配列が格納されていない領域はデフォルトで初期化されます。
reserve_hear()
は配列の先頭部に指定したサイズの領域を確保します。コンテナオブジェクトからは参照できない領域となります。例えばパケットペイロードのヘッダ部分を読み飛ばした部分配列にアクセスするようなコンテナとして利用できるようにします。確保した領域を戻しすべてアクセスできるようにコンテナを戻すには確保時と同じ負の値を与えます。
redim()
は利用領域のサイズを変更します。reserve()
と違い、未使用領域の初期化を行いません。
要素にアクセスします。
i
に負の値を与えるとバッファー末尾からの要素となります。-1
の場合は末尾の要素、-2
は末尾から一つ手前となります。
uint8_t
型の配列オブジェクト(smplbuf<uint8_t, *>
)は、mwx::stream
の派生オブジェクトに対して、そのまま出力できます。
Serial
などmwx::stream
の派生オブジェクトに対して、バイト列を出力します。
ストリームへの出力目的で利用します。<<演算子の実装に用いられています。
mwx::stream
では<<
演算子やprintfmt()
メソッドと行ったストリームに対してバイト列を出力するための関数・演算子が定義されています。uint8_t
型のsmplbufの配列を出力先と見立ててストリーム出力手続きを行えます。
方法は2種類あります。
メモリバッファ取り扱い方法()に応じて3種類のクラス名が定義されています。
ty
で指定するで、p
で指定したバッファを用います。バッファの最大長はmax_siz
で、バッファの有効データ長をsiz
で指定します。
ty
で指定するで初期化を行います。
ty
で指定するで、siz
で指定したサイズをヒープに確保して初期化します。
パケットデータのバイト列を入力として、パケットの種別を判定します。戻り値はです。
TwePacketTwelite
クラスは、標準アプリを解釈したものです。
smplbuf
は要素の型T
とで指定したメモリ領域に対して配列の操作を提供するコンテナクラスです。alloc
の指定は煩雑であるためusing
を用いた別名定義が行っています。
により生成されるヘルパーオブジェクトを利用する。
mwx::stream
をを利用する。
クラス名
内容
alloc_attach<T>
すでにあるバッファを指定する
alloc_local<T, int N>
Nバイトのバッファを内部に静的確保する
alloc_heap<T>
指定したサイズをヒープに確保する
名前
解説
PKT_ERROR
パケット解釈前やパケット種別が特定できないなど、TwePacketには意味のあるデータが格納されていない
PKT_TWELITE
標準アプリ App_Twelite の 0x81 コマンドを解釈したもの
PKT_PAL
TWELITE PALのシリアル形式を解釈したもの
PKT_APPIO
PKT_APPUART
PKT_APPTAG
無線タグアプリApp_TagのUARTメッセージを解釈したもの。センサ固有部分は解釈されずpayloadとしてバイト列を報告します。
PKT_ACT_STD
アクト(Act)のサンプルなどで使用される出力書式。
値
解説
MSB(bit31)がセットされている
宛先としてシリアル番号を指定しています。
0x00
-0xFF
宛先として論理ID(8bit)が指定されています。
定数 | 種別 |
| アスキー形式 |
| バイナリー形式 |
====== | 元データのバイト数 | バイト数 | 解説 |
ヘッダ | 1 |
|
データ部 | N | 2N | 元データの各バイトをアスキー文字列2文字(A-F は大文字)で表現します。
例えば 0x1F は |
チェックサム | 2 | データ部の各バイトの和を8ビット幅で計算し2の補数をとります。つまりデータ部の各バイトの総和+チェックサムバイトを8ビット幅で計算すると0になります。
チェックサムバイトをアスキー文字列2文字で表現します。
例えば |
フッタ | 2 | [CR] (0x0D) [LF] (0x0A) を指定する。 |
====== | 元データのバイト数 | 形式におけるバイト数 | 解説 |
ヘッダ | 2 |
|
データ長 | 2 | データ長はビッグエンディアン形式の2バイトで、MSB (0x8000) を設定した上、データ部の長さを指定します。
例えばデータ部の長さが 8 バイトなら |
データ部 | N | N | 元データを指定します。 |
チェックサム | 1 | データ部の各バイトの XOR を計算します。
例えばデータ部が |
フッタ | (1) | チェックサムが事実上の終端です。無線モジュールからの出力では |
クラス名(別名定義) メモリ確保 | 内容 |
| すでにあるバッファを |
| Nバイトのバッファを内部に確保する |
|
|
TwePacketAppIO
クラスは、標準アプリApp_IOのシリアルメッセージ(0x81)を解釈したものです。
パケットデータ内の諸情報はparse<TwePacketIO>()
実行後にDataTwelite
に格納されます。
uint8_t
型のsmplbuf配列を参照したstream_helper ヘルパーオブジェクトを経由して、mwx::stream
による演算子やメソッドを用います。
ヘルパーオブジェクトの型名は長くなるためauto&&
により解決しています。このオブジェクトに対して<<
演算子などmwx::stream
で定義されたインタフェースを利用できます。
生成されたヘルパーオブジェクトbs
は生成時に大本の配列b
の先頭位置から読み書きを始めます。配列の末尾の場合はappend()
によりデータを追加します。読み書きを行うたびに位置は次に移動していきます
ヘルパー関数では読み出し用の>>
演算子が利用できます。
FIFOキューを構造のコンテナクラスです。
smplque
は要素の型T
とメモリの確保方法alloc
で指定したメモリ領域に対してFIFOキューの操作を提供するコンテナクラスです。alloc
の指定は煩雑であるためusing
を用いた別名定義が行っています。
要素型は原則として数値や数値などを格納する構造体を想定しています。デストラクタによる破棄手続きが必要なオブジェクトを格納することを想定していません(キューから要素を抹消する際にオブジェクトを抹消する処理をしていないため)。
宣言時に割り込み禁止設定を行うクラスIntr
を登録することが出来ます。このクラスは指定しない場合は、割り込み禁止制御を行わない通常の動作となります。
オブジェクトの宣言例です。宣言の直後に初期化用のメソッド呼び出しを行います。いずれも初期化直後の最大サイズは128バイトで、初期サイズは0で何も格納されていません。最大サイズは変更できません。
FIFOキューですのでpush()
,pop()
,front()
といったメソッドを用いて操作します。
イテレータによるアクセスも可能です。
型T
でサイズN
のコンテナを宣言します。宣言後に初期化のメソッドを呼び出します。
smplque_local
は、内部に固定配列により領域を確保します。コンストラクタによる初期化も可能です。
smplque_attach
では、使用するバッファの先頭ポインタT* buf
と配列の初期サイズsize
と最大サイズN
を指定します。コンストラクタによる初期化も可能です。
smplque_heap
は、HEAP領域(解放は不可能だが随時確保可能なメモリ領域)にメモリを確保します。一度確保したら開放できない領域ですので通常はグローバル領域に定義します。領域確保はinit_heap()
で行います。コンストラクタによるメモリ確保はできません。必ずinit_heap()
を呼び出して利用してください。
グローバルオブジェクトを生成する場合は、コンストラクタによる初期化が行なえません。実行初期(setup()
を推奨)に初期化関数init_local()
,attach()
,init_heap()
を呼び出すようにしてください。
push()
はエントリをキューに追加します。
pop()
はエントリをキューから抹消します。
front()
は先頭のエントリ(一番最初に追加されたもの)を参照します。
back()
は末尾のエントリ(一番最後に追加されたもの)を参照します。
pop_front()
は先頭のエントリを戻り値として参照し、同時にそのエントリをキューから抹消します。
empty()
は配列に要素が格納されていない場合にtrue
を戻します。is_full()
は反対に配列サイズ一杯まで要素が格納されているときにtrue
を戻します。
size()
はキューに格納されている要素数を返します。
capacity()
はキューの最大格納数を返します。
キューのすべての要素を抹消します。
要素にアクセスします。0
が最初に追加した要素です。
begin()
とend()
によるイテレータを取得できます。イテレータの先頭はキューの最初に登録した要素です。イテレータを用いることで範囲for文やアルゴリズムが利用できます。
応用としてaxis_xyzt構造体の特定のメンバーに注目したイテレータによるアクセスがあります。
mwx::stream に printf の書式を入力
mwx::stream
の << 演算子に対してフォーマット書式を書き出すヘルパークラスです。ライブラリ内では Using format=mwx::mwx_format;
として別名定義しています。
可変数引数リストに登録できる引数は最大8つです。doubleやuint64_t型など64bitのパラメータが含まれる場合は引数の数が制限されます。制限を超えた場合はstatic_assertによるコンパイルエラーになります。
コンストラクタで受け取った引数リストを、パラメータパックの展開機能を用いてクラス内部変数に格納する
operator <<
が呼び出された時点で、fctprintf()
を呼び出し、ストリームにデータを書き出す
コンストラクタでは、書式のポインタとパラメータを保存します。続く <<
演算子による呼び出しでフォーマットを解釈して出力処理を行います。
fmt
は本オブジェクトが破棄されるまで、アクセス可能であることが必要です。
入出力ストリーム
入出力ストリームを処理する上位クラスです。
CRTP (Curiously Recurring Template Pattern) 手法を用いたポリモーフィズムにより、いくつかのクラス(Serial, Wire, SPI, smplbuf
) にインタフェースを提供します。
CRTP では下位クラスは template class Derived : public stream<Derived>;
のように定義し、上位クラスからも下位クラスのメソッドを参照します。
本クラスでは print
メソッド、<<
演算子などの共通処理の定義を行い、下位クラスで実装した write()
メソッドなどを呼び出すことで、仮想関数を用いるのと近い実装を行っています。
下位クラスでは、以下に列挙する関数を実装します。
入力が存在する場合は 1、存在しない場合は 0 を返します。
本実装の戻り値はバッファ長ではありません。
出力をフラッシュ(出力完了まで待つ)します。
ストリームより1バイトデータを入力します。データが存在しない場合は -1
を戻します。
ストリームに1バイト出力します。
1バイト出力を行うスタティック関数です。クラスメソッドではないため、メンバー変数等の情報は利用できません。替わりにパラメータとして渡される vp にクラスインスタンスへのポインタを渡します。
このスタティック関数は内部的に利用されfctprintf()
の1バイト出力関数として関数ポインタが渡ります。これを用いてprint
メソッドなどを実装しています。
1バイト出力します。
各種整形出力を行います。
printf 形式での出力を行います。
TWESDK/TWENET/current/src/printf/README.md 参照
バイト列として出力する際は、uint8_t, uint16_t, uint32_t
型にキャストします。また文字列として数値出力する場合は明示的にint
形にキャストするようにしてください。
1バイト型は型名によって取り扱いが違います。通常はサイズを意識したuint8_t[S]
型を用いるようにしてください。
>>
演算子を用いた入力タイムアウトとエラーを管理します。
set_timeout()
によりタイムアウト時間を指定し、>>
演算子により入力処理を行います。所定時間内までに入力が得られない場合は get_error_status()
によりエラー値を読み出せます。clear_error_status()
によりエラー状況をクリアします。
入力処理を行います。
setup()
内では実行できません。
ポーリング待ちを行うため、タイムアウトの時間設定(タイムアウト無しなど)によっては、ウォッチドッグタイマーが発動してリセットする場合があります。
通常はloop()
中で以下のような読み出しを行います。
以下に読み出し格納できる型を列挙します。
twe::stream へのバッファ出力をフラッシュする。
mwx::stream
の出力バッファをフラッシュする。flush()
メソッドを呼び出すヘルパークラスへのインスタンス。
シリアルポートの場合は出力完了までポーリング待ちを行う
mwx::simpbuf
バッファの場合は 0x00
を末尾に出力する(サイズは変更しない)
twe::stream に改行コードを出力する
mwx::stream
の <<
演算子に対して改行コード (CR LF) を出力するためのヘルパークラスのインスタンスです。
stream_helperは、mwx::stream
インタフェースを付与するヘルパーオブジェクトです。データクラスを参照するヘルパーオブジェクトを生成し、ヘルパーオブジェクト経由でデータの入出力を行います。
以下にはsmplbufの配列b
からヘルパーオブジェクトbs
を生成しmwx::stream::operator <<()
演算子によるデータ入力を行っています。
stream_helper はデータ配列をストリームに見立てて振舞います。
内部にはデータ配列中の読み書き位置を保持しています。次のようにふるまいます。
読み出しまたは書き込みをすると次の読み書き位置に移動します。
最期のデータを読み出した後、またはデータを末尾に追記した後には、読み書き位置は終端となります。
読み書き位置が終端の場合、
available()
がfalse
になります。
読み出しは出来ません。
書き込みは書き込み可能範囲であれば追記します。
読み書き位置を先頭に移動します。
読み書き位置を設定します。
読み書き位置を返します。終端位置の場合は-1
を返します。
読み書き位置が終端であれば0
を返します。終端でなければそれ以外の値を返します。
stream_helper は、データクラス (, ) のメンバー関数より生成します。
パラメータ
解説
fmt
フォーマット書式。
TWESDK/TWENET/current/src/printf/README.md 参照
...
フォーマット書式に応じたパラメータ。 ※ 最大数は4で、5つ以上のパラメータではコンパイルエラーとなる。
※ 書式との整合性はチェックしないため、不整合な入力に対しては安全ではない。
パラメータ
解説
戻り値 int
0: データなし 1:データあり
パラメータ
解説
n
出力したい文字。
戻り値 size_t
出力が成功すれば 1、失敗すれば 0。
パラメータ
解説
out
出力したい文字
vp
クラスインスタンスへのポインタ 通常は、元のクラスにキャストして write() メソッドを呼び出す
パラメータ
解説
val
整形出力したい数値型
base
出力形式
BIN 二進数 / OCT 8進数 / DEC 10進数 / HEX 16進数
place
小数点以下の桁数
戻り値 size_t
書き出したバイト数
引数型
解説
char
1バイト出力 (数値としてフォーマットはしない)
int
整数出力 (printf の "%d")
double
数値出力 (printf の "%.2f")
uint8_t
1バイト出力する(char型と同様)
uint16_t
2バイト出力する(ビッグエンディアン順)
uint32_t
4バイト出力する(ビッグエンディアン順)
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
により生成できる。T
は uint8_t
型を想定する。(右辺値)
bytelist()
std::initializer_list
を用いるバイト列の出力
smplbuf<uint8_t,AL>&
uint8_t
型の配列クラスの内容を出力する。
ALC
はメモリ確保手段。
smplbuf<uint8_t, AL>::to_stream()
smplbuf<T>
のデータを出力する
T
は uint8_t
型、AL
はメモリ確保手段。
引数型
解説
centisec
1/10秒単位でタイムアウト時間を設定します。
0xff
を指定した場合は、タイムアウトを無効とします。
値
意味
0
エラーなし
1
エラー状況
引数型
解説
uint8_t, char_t
1バイト入力
uint16_t
2バイト入力(ビッグエンディアン順)
uint32_t
4バイト入力(ビッグエンディアン順)
uint8_t[S]
S
バイト分入力
(S
は固定配列のサイズ指定)
null_stream(int n)
n
バイト読み捨てる
whence | 設定位置 |
| 先頭位置から設定します。 |
| 現在位置を基準に |
| 終端位置にします。 |
パラメータ | 解説 |
|
|