<BRD_APPTWELITE>
を用いたサンプルです。<STG_STD>
をインクルードしています。setup()
内で登録しないと動作しません。set
オブジェクトを取得しています。続いて以下の処理を行っています。"BRD_APPTWELITE"
に設定(メニューで利用される)set.reload()
により保存された設定値を読み出すOPT_BITS
とLID
の値を変数にコピーする<BRD_APPTWELITE>
を登録しています)。以下のように use の後に <>
で登録したいボードの名前を指定します。auto&&
)にて得られた戻り値として、参照型でのボードオブジェクトが得られます。このオブジェクトにはボード特有の操作や定義が含まれます。以下ではボードオブジェクトを用い、M1ピンの状態を確認しています。M1ピンがLOであれば、LID=0、つまり親機アドレスと設定します。the_twelite
に設定を反映するには <<
を用います。TWENET::rx_when_idle()
受信回路をオープンにする指定です。<<, >>
演算子は本来ビットシフト演算子ですが、その意味合いと違った利用とはなります。MWXライブラリ内では、C++標準ライブラリでの入出力利用に倣ってライブラリ中では上記のような設定やシリアルポートの入出力で利用しています。<>
には <NWK_SIMPLE>
を指定します。<NWK_SIMPLE>
の設定です。先にインタラクティブモードの設定値を反映させます。反映される項目はLIDと再送回数です。このアプリケーションではM1ピンの状態によってLID=0にする場合があるため、3行目で再度LIDを設定しています。Analogue.setup()
で行います。パラメータのtrue
はADC回路の安定までその場で待つ指定です。2番目のパラメータは、ADCの開始をTimer0に同期して行う指定です。Analogue.begin()
を呼びます。パラメータはADC対象のピンに対応するビットマップです。pack_bits()
関数を用います。可変数引数の関数で、各引数には1を設定するビット位置を指定します。例えばpack_bits(1,3,5)
なら2進数で 101010
の値が戻ります。この関数はconstexpr
指定があるため、パラメータが定数のみであれば定数に展開されます。BRD_APPTWELITE::
にはPIN_AI1..4
が定義されています。App_Tweliteで用いるAI1..AI4に対応します。AI1=ADC1, AI2=DIO0, AI3=ADC2, AI4=DIO2 と割り当てられています。PIN_ANALOGUE::
にはADCで利用できるピンの一覧が定義されています。Buttons.setup()
で行います。パラメータの 5 は、値の確定に必要な検出回数ですが、設定可能な最大値を指定します。内部的にはこの数値をもとに内部メモリの確保を行っています。Buttons.begin()
で行います。1番目のパラメータは検出対象のDIOです。BRD_APPTWELITE::
に定義されるPIN_DI1-4
(DI1-DI4) を指定しています。2番めのパラメータは状態を確定するのに必要な検出回数です。3番めのパラメータは検出間隔です。4
を指定しているので4msごとに5回連続で同じ値が検出できた時点で、HIGH, LOWの状態が確定します。true
にするとソフトウェア割り込みが有効になります。Timer0.begin()
を呼び出したあと、タイマーが稼働します。setup()
関数の末尾で the_twelite.begin()
を実行しています。Serial
オブジェクトには const char* 型の文字列や、int型(他の整数型はNG)、printfとほぼ同じ振る舞いをするformat()
、改行文字を出力するcrlf
などを<<演算子に与えます。mwx::
を省略している場合もあります。上記ではmwx::crlf
と記載していますがcrlf
と記載しても構いません。mwx::名前空間は、一部を省略可能とするように設計しています。loop()
が呼び出されます。loop()
を抜けた後は CPU が DOZE モードに入り、低消費電流で新たな割り込みが発生するまでは待機します。Buttons.read()
により読み出します。bp & (1UL << 12)
を評価すれば HIGH / LOW が判定できます。ビットが1になっているものがHIGHになります。u8DI_BM
に格納しています。ここではMWXライブラリで用意したcollect_bits()
関数を用いています。collect_bits()
は、上述のpack_bits()
と同様のビット位置の整数値を引数とします。可変数引数の関数で、必要な数だけパラメータを並べます。上記の処理では bit0 は DI1、bit1 は DI2、bit2 は DI3、bit3 は DI4の値としてu8DI_BMに格納しています。Buttons.available()
を起点に送信処理を行います。transmit()
処理の内容は後述します。loop()
で available になります。次の ADC が開始するまでは、データは直前に取得されたものとして読み出すことが出来ます。Analogue.read()
または Analogue.read_raw()
メソッドを用います。read()
はmVに変換した値、read_raw()
は 0..1023 のADC値となります。パラメータにはADCのピン番号を指定します。ADCのピン番号はPIN_ANALOGUE::
やBRD_APPTWELITE::
に定義されているので、こちらを利用しています。loop()
中で比較的長い時間のかかる処理をしている場合は注意が必要です。Analogue
には、変換終了後に割り込みハンドラ内から呼び出されるコールバック関数を指定することが出来ます。例えば、このコールバック関数からFIFOキューに値を格納する処理を行い、アプリケーションループ内ではキューの値を逐次読み出すといった非同期処理を行います。Timer0
は32Hzで動作しています。タイマー割り込みが発生直後の loop()
で available になります。つまり、秒32回の処理をします。ここでは、ちょうど1秒になったところで送信処理をしています。Timer0
がavailableになったときにu16ct
をインクリメントします。このカウンタ値をもとに、32回カウントが終わればtransmit()
を呼び出し無線パケットを送信しています。u8DI_BM
とau16AI[]
の値判定は、初期化直後かどうかの判定です。まだDI1..DI4やAI1..AI4の値が格納されていない場合は何もしません。MWX_APIRET
はuint32_t
型のデータメンバを持つ戻り値を取り扱うクラスです。MSB(bit31)が成功失敗、それ以外が戻り値として利用するものです。the_twelite.network.use<NWK_SIMPLE>()
で取得します。そのオブジェクトを用いて.prepare_tx_packet()
によりpkt
オブジェクトを取得します。pkt
オブジェクトはif節の終わりまで有効です。pktオブジェクトはbool型の応答をし、ここではTWENETの送信要求キューに空きがあって送信要求を受け付ける場合にtrue
、空きがない場合にfalse
となります。the_twelite
の初期化設定のように<<
演算子を用いて行います。tx_addr()
パラメータに送信先アドレスを指定します。0x00
なら自分が子機で親機宛に、0xFE
なら自分が親機で任意の子機宛のブロードキャストという意味です。tx_retry()
パラメータに再送回数を指定します。例の1
は再送回数が1回、つまり合計2回パケットを送ります。無線パケット1回のみの送信では条件が良くても数%程度の失敗はあります。tx_packet_delay()
送信遅延を設定します。一つ目のパラメータは、送信開始までの最低待ち時間、2番目が最長の待ち時間です。この場合は送信要求を発行後におよそ0msから50msの間で送信を開始します。3番目が再送間隔です。最初のパケットが送信されてから10ms置きに再送を行うという意味です。pkt.get_payload()
により simplbuf<uint8_t>
型のコンテナとして参照できます。このコンテナに上記の仕様に基づいてデータを構築します。pack_bytes()
を用意しています。pack_bytes
の最初のパラメータはコンテナを指定します。この場合はpkt.get_payload()
です。pack_bytes
で対応する型の値を必要な数だけ指定します。pack_bytes
は内部で.push_back()
メソッドを呼び出して末尾に指定した値を追記していきます。make_pair()
は標準ライブラリの関数でstd::pair
を生成します。文字列型の混乱(具体的にはペイロードの格納時にヌル文字を含めるか含めないか)を避けるための指定です。make_pair()
の1番目のパラメータに文字列型(char*
やuint8_t*
型、uint8_t[]
など)を指定します。2番目のパラメータはペイロードへの格納バイト数です。uint8_t
型でDI1..DI4のビットマップを書き込みます。au16AI
配列の値を順に書き込んでいます。この値はuint16_t
型で2バイトですが、ビッグエンディアンの並びで書き込みます。begin(), end()
によるイテレータによるアクセスが可能なコンテナクラスなどは、この構文が使用できます。au16AIの型もコンパイル時に判定できるため auto&&
(ユニバーサル参照)で型の指定も省略してます。pkt
オブジェクトのpkt.transmit()
メソッドを用います。戻り値としてMWX_APIRET
型を返していますが、このアクトでは使っていません。on_rx_packet()
が呼び出されます。the_twelite.receiver
による手続きでは一旦受信パケットを内部キュー(2パケットまで格納)に格納してからの処理でしたが、on_rx_packet()
ではTWENETライブラリからのコールバックから直接呼び出され、より取りこぼし等が発生しにくい手続きです。ただしloop()
文中で長時間処理を止めてしまうような記述を行うと、同じように取りこぼしの原因となります。rx
をはパラメータとして渡されます。rx
から無線パケットのアドレス情報やデータペイロードにアクセスします。パラメータhandled
は通常利用しません。<NWK_SIMPLE>
では、8bitの論理IDと32bitのロングアドレスの2種類が常にやり取りされます。送り先を指定する場合はロングアドレスか論理アドレスのいずれかを指定します。受信時には両方のアドレスが含まれます。transmit()
の時に使ったpack_bytes()
の対になる関数expand_bytes()
が用意されています。char
型の配列を宣言しています。サイズが5バイトなのは末尾にヌル文字を含め、文字出力などでの利便性を挙げるためです。末尾の{}
は初期化の指定で、5バイト目を0にすれば良いのですが、ここでは配列全体をデフォルトの方法で初期化、つまり0
にしています。expand_bytes()
により4バイト文字列を取り出しています。パラメータにコンテナ型を指定しない理由は、この続きを読み出すための読み出し位置を把握する必要があるためです。1番目のパラメータでコンテナの先頭イテレータ(uint8_t*
ポインタ)を指定します。.begin()
メソッドにより取得できます。2番目のパラメータはコンテナの末尾の次を指すイテレータで.end()
メソッドで取得できます。2番目はコンテナの末尾を超えた読み出しを行わないようにするためです。make_pair
によって文字列配列とサイズのペアを指定します。expand_bytes()
の戻り値により判定してください。expand_bytes()
の戻り値は uint8_t*
ですが、末尾を超えたアクセスの場合はnullptr(ヌルポインタ)
を戻します。<NWK_SIMPLE>
でのパケット構造の要件も満足する必要があるため、シンプルネットワークを使用しない他のアプリケーションが同じ構造のパケットを定義しない限り(非常にまれと思われます)、パケットの混在受信は発生しません。expand_bytes()
の戻り値np
を1番目のパラメータにしています。先に読み取った4バイト文字列識別子の次から読み出す指定です。2番目のパラメータは同様です。format()
を用いています。>>
演算子向けにprintf()
と同じ構文を利用できるようにしたヘルパークラスですが、引数の数が4つまでに制限されています。(Serial.printfmt()
には引数の数の制限がありません。)"DI:%04b"
は"DI:0010"
のようにDI1..DI4のビットマップを4桁で表示します。3行目の"/%04d"
は"/3280/0010/0512/1023/1023"
のように Vcc/AI1..AI4の値を順に整数で出力します。5行目のmwx::crlf
は改行文字列を出力します。digitalWrite()
はディジタル出力の値を変更します。1番目のパラメータはピン番号で、2番目はHIGH
(Vccレベル)かLOW
(GNDレベル)を指定します。Timer?.change_duty()
はPWM出力のデューティ比を変更します。パラメータにデューティ比 0..1024 を指定します。最大値が1023でないことに注意してください(ライブラリ内で実行される割り算のコストが大きいため2のべき乗である1024を最大値としています)。0
にするとGNDレベル、1024
にするとVccレベル相当の出力になります。