ビヘイビアは、指定の方法でクラスを定義することで、the_twelite クラスオブジェクトに登録できるようになります。登録したビヘイビアはTWENETに組み込まれて動作し、ユーザコードではアプリケーションの振る舞いを記述できるようになります。ループでの記述ではできなかったTWENETからの割り込みやイベントのコールバック関数を定義することが出来ます。ループでの記述に比べ、定義が多くなりますが、より複雑なアプリケーションを記述するのに向いています。
ビヘイビアの定義には下記に示すようなクラス定義が必要です。
コピー class MY_APP_CLASS : MWX_APPDEFS_CRTP(MY_APP_CLASS)
{
public :
static const uint8_t TYPE_ID = 0x 01 ;
// load common definition for handlers
#define __MWX_APP_CLASS_NAME MY_APP_CLASS
#include "_mwx_cbs_hpphead.hpp"
#undef __MWX_APP_CLASS_NAME
public :
// constructor
MY_APP_CLASS () {}
void _setup () {}
void _begin () {}
public :
// TWENET callback handler (mandate)
void loop () {}
void on_sleep ( uint32_t & val) {}
void warmboot ( uint32_t & val) {}
void wakeup ( uint32_t & val) {}
void on_create ( uint32_t& val) { _setup (); }
void on_begin ( uint32_t& val) { _begin (); }
void on_message ( uint32_t& val) { }
public :
void network_event (mwx :: packet_ev_nwk & pEvNwk) {}
void receive (mwx :: packet_rx & rx) {}
void transmit_complete (mwx :: packet_ev_tx & evTx) {}
}; 上記の例ではMY_APP_CLASSという名前でビヘイビアクラスを定義しています。いくつかの箇所にMY_APP_CLASSの記述が必要です。
クラス名の定義と、ベース(親)クラスの定義をします。MWX_APPDEFS_CRTP()はマクロです。
ここでは必要な定義を #include により取り込んでいます。
コンストラクタの定義です。
メインループで、グローバル定義のloop()と同じ役割の関数です。
on_create()はオブジェクト生成時(use<>()メソッド)に呼び出されます。valは将来の拡張のためのパラメータです。
on_begin()はsetup()終了後に呼び出されます。valは将来の拡張のためのパラメータです。
スリープ前に呼び出されます。valは将来の拡張のためのパラメータです。
スリープ復帰時の初期段階で呼び出されます。valは将来の拡張のためのパラメータです。
この時点でまだペリフェラルが初期化されていません。スリープ起床要因の確認ができます。
スリープ復帰時に呼び出されます。valは将来の拡張のためのパラメータです。
パケットが受信されたとき、受信したパケット情報をrxとして呼び出されます。
transmit_complete()
パケット送信完了時に送信情報をevTxとして呼び出されます。evTx.u8CbIdが送信時のIDでevTx.bStatusが送信の成功(1)失敗(0)を示すフラグです。
ビヘイビアのハンドラ(割り込み、イベント、状態定義)はcppファイルに定義します。ファイルは分割できず、全てのハンドラ定義を一つのファイル中に記述します。
circle-exclamation
ハンドラの定義をしないビヘイビアの場合でも、必ず、下記のcppファイルを作成します。
cppファイルの冒頭と末尾にはMWXライブラリの必要な定義(#include "_mwx_cbs_cpphead.hpp")をインクルードする必要があります。
ファイルの冒頭には、上記のようにビヘイビア定義の.hppファイルをインクルードします。__MWX_APP_CLASS_NAMEにはビヘイビアのクラス名を指定します。上記ではMY_APP_CLASSです。
ファイルの末尾では必要な定義(#include "_mwx_cbs_cpptail.cpp")をインクルードします。
ハンドラ定義は以下の例のように記述します。定義の種別については後述します。定義用のマクロを用いて利用したいハンドラの定義を記述します。利用しないハンドラは記述しないようにしてください。
MWX_???_INT()は割り込みハンドラの定義、MWX_???_EVENT()はイベントハンドラの定義、MWX_STATE()はステートマシンの状態定義です。
割り込みハンドラは、マイコンの割り込みが発生したときに現在実行中のコードを中断して実行されます。このため、可能な限り短い処理を記述することが望ましく、また、変数等の操作に対しても細心の注意が必要です。
割り込みハンドラのパラメータにはuint8_t& handledがあり、この値をtrueにセットすることで、続くイベント呼び出しを行いません。
handledがfalseのまま割り込みハンドラを終了した場合、アプリケーションループ(通常コード)の中でイベントハンドラが呼び出されます。イベントハンドラにはhandledのパラメータはありません。イベントハンドラは通常コードですので、比較的大きな処理を行うことが出来ます。イベントハンドラのオーバーヘッドも発生するため、頻繁な割り込み都度呼び出されるような処理の場合、処理しきれなくなる可能性があります。また、イベントの発生はシステム内部のFIFOキューにより処理されるため、一定時間内に処理できない場合はイベントが消失する場合もあります。
以下にハンドラ関数定義用のマクロの解説を行います。
DIO(ディジタルIO)割り込み・イベントです。Nは対象DIOの番号を指定します。argは将来の拡張のための定義です。
割り込みを発生させるためにはpinMode() による適切な入力設定, attachDioInt() による割り込み開始の設定が必要です。
TickTimer割り込み・イベントです。argは将来の拡張のための定義です。
triangle-exclamation
TickTimerのhandledフラグをtrueにセットしてはいけません。TWENETが動作しなくなります。
タイマー割り込み・イベントです。Nは対象タイマーの番号を指定します。argは将来の拡張のための定義です。
割り込みを発生させるためには、Timerオブジェクト をソフトウェア割り込みを有効にして開始します。
circle-exclamation
MWXライブラリで標準的に定義しない、その他の割り込み・イベントの定義です。AHIペリフェラルマニュアルの理解が必要です。
その他の割り込み・イベントは以下のハンドラ関数で受けることが出来ます。これらは将来的に専用のハンドラが定義された場合、利用できなくなります。
ペリフェラル (AHI) の割り込みハンドラのu32DeviceIdがarg、u32ItemBitmapがarg2に対応します。
状態マシン(ステートマシン)は、メッセージを受け取り、そのメッセージに応じて状態を遷移させながら動作させるアプリケーションの記述方法です。
PAL_AMB-behavior サンプルでは、センサーの動作開始からセンサーの値取得、無線パケット送信から送信完了まで、スリープ遷移といったアプリケーションの動作の流れを記述しています。実例として参考にしてください。
受け取るイベントは以下となります。
システム始動時に呼び出される。電源投入直後はパラメータが0で呼び出されます。実行初期であるため、通常処理を行う状態に遷移する場合は一旦begin()メソッドから PEV_Process() を呼び出し動作を開始させます。
スリープ復帰後も呼び出されるがパラメータは0以外です。この状態からは通常処理を行えます。
状態遷移直後に新しい状態で呼び出されます。ある状態に遷移したときに最初に実行される処理を記述します。
状態をsに設定します。
状態ハンドラを抜けると次の状態に遷移し、続けてE_EVENTS_NEW_STATEイベントで状態ハンドラが呼び出されます。
PEV_u32Elaspsed_ms()
状態遷移してからの経過時間[ms]を返します。タイムアウトを管理するような目的で使用します。
上記の例では100ms経過した時点でシステムリセットを行います。
状態ハンドラ外から呼び出します。状態ハンドラをイベントevパラメータu32evargで実行します。
送信完了イベントを状態マシンに伝えます。つまり状態ハンドラの呼び出しを行います。
triangle-exclamation
直接状態ハンドラを呼び出すことは行わないでください。E_EVENT_NEW_STATEが実行されないなどの問題が発生します。
PEV_KeepStateOnWakeup()
スリープ直前に設定します。スリープ復帰後に、直前の状態を維持します。つまり、スリープを開始した状態でE_EVENT_START_UPで状態ハンドラが呼び出されます。
PEV_is_coldboot()
イベントが起床時のE_EVENT_START_UPかどうか判定します。
PEV_is_warmboot()
イベントがスリープ復帰時のE_EVENT_START_UPかどうか判定します。