Scratch

テンプレートコードです。

このアクトには以下が含まれます。

  • 無線パケットの送信 ('t' キー)

  • スリープ ('s'キー)

  • シリアルポートからの入力 - Serial

  • ディジタル(ボタン)入力 - Buttons

setup()

void setup() {
/*** SETUP section */
tx_busy = false;
// the twelite main class
the_twelite
<< TWENET::appid(APP_ID) // set application ID (identify network group)
<< TWENET::channel(CHANNEL) // set channel (pysical channel)
<< TWENET::rx_when_idle(); // open receive circuit (if not set, it can't listen packts from others)
// Register Network
auto&& nwk = the_twelite.network.use<NWK_SIMPLE>();
nwk << NWK_SIMPLE::logical_id(0xFE); // set Logical ID. (0xFE means a child device with no ID)
/*** BEGIN section */
Buttons.begin(pack_bits(PIN_BTN), 5, 10); // check every 10ms, a change is reported by 5 consequent values.
the_twelite.begin(); // start twelite!
/*** INIT message */
Serial << "--- Scratch act ---" << mwx::crlf;
}

the_tweliteを設定してアプリケーションID APP_ID, 無線チャネルCHANNEL、受信有を設定します。

またnwkを生成し、子機アドレス0xFEを指定しています。このアドレスは子機でアドレスを指定していない名無しの子機という意味です。

設定できるアドレスは0x00: 親機,0x01~0xEF: 子機, 0xFE:子機アドレス未指定の範囲です。

送信先として指定するアドレスは0x00は親機宛、0x01~0xEFは指定の親機アドレス、0xFEは任意の子機アドレス、0xFFは親機を含む任意のアドレスです。

またButtonsオブジェクトを初期化します。連続参照によるチャタリング抑制アルゴリズムです。10msごとに5回連続同じ値になれば対象のポート(PIN_BTNのみ)のHIまたはLOWを確定します。pack_bits(N1, N2, ..)1UL<<N1 | 1UL << N2 | ...を行いビットマップを生成します。

the_twelite.begin(); // start twelite!

the_tweliteを開始するための手続きです。act0..4では出てきませんでしたがthe_tweliteの設定や各種ビヘイビアの登録を行った場合は、必ず呼び出すようにしてください。

begin()

void begin() {
Serial << "..begin (run once at boot)" << mwx::crlf;
}

始動時setup()の後に1回だけ呼び出されます。メッセージの表示のみ。

loop()

ボタン(スイッチ)の入力検出

if (Buttons.available()) {
uint32_t bm, cm;
Buttons.read(bm, cm);
if (cm & 0x80000000) {
// the first capture.
}
Serial << int(millis()) << ":BTN" << format("%b") << mwx::crlf;
}

Buttonsによる連続参照により状態を確定します。ボタン状態が変化したらシリアルに出力します。

シリアルからの入力

while(Serial.available()) {
int c = Serial.read();
Serial << '[' << char(c) << ']';
switch(c) {
case 'p': ... // millis() を表示
case 't': ... // 無線パケットを送信 (vTransmit)
if (!tx_busy) {
tx_busy = Transmit();
if (tx_busy) {
Serial << int(millis()) << ":tx request success! ("
<< int(tx_busy.get_value()) << ')' << mwx::crlf;
} else {
Serial << int(millis()) << ":tx request failed" << mwx::crlf;;
}
}
case 's': ... // スリープする
Serial << int(millis()) << ":sleeping for " << 5000 << "ms" << mwx::crlf << mwx::flush;
the_twelite.sleep(5000);
break;
}
}

Serial.available()trueの場合は、シリアルポートからの入力が保存されています。シリアルから1文字読み込んで、入力文字に応じた処理をします。

tを入力して無線送信

't'を入力したときは送信を行います。このサンプルではtx_busyフラグを用い連続的に入力は行わないようにしています。

送信要求は一定数までキューに保存されるため、キューの範囲(3パケット)で要求を積むことは可能です。

以下はif(!tx_busy)の判定をしないようにして 'tttt'と連続的に入力した場合の処理例です。4つ目の要求でキューが一杯になって要求は失敗しています。Transmit().prepare_tx_packet()で得られたpktオブジェクトがfalseになります。

送信タイミングはランダム化されるため、送信完了は送信要求順にはなりません。

--- Scratch act ---
..begin (run once at boot)
[t]11591:Transmit()
11592:tx request success! (1)
[t]11593:Transmit()
11593:tx request success! (2)
[t]11594:Transmit()
11595:tx request success! (3)
[t]11595:Transmit()
TX QUEUE is FULL
11596:tx request failed
11654:tx completed!(id=2, stat=1)
11719:tx completed!(id=3, stat=1)
11745:tx completed!(id=1, stat=1)

sを入力してスリープ

the_twelite.sleep(5000);

5000ms=5秒のスリープを実施します。復帰後はwakeup()が実行されます。

wakeup()

void wakeup() {
Serial << int(millis()) << ":wake up!" << mwx::crlf;
}

スリープ起床時に最初に呼び出されます。メッセージの表示のみ。

Transmit()

MWX_APIRET Transmit() {
Serial << int(millis()) << ":Transmit()" << mwx::crlf;
if (auto&& pkt = the_twelite.network.use<NWK_SIMPLE>().prepare_tx_packet()) {
// set tx packet behavior
pkt << tx_addr(0xFF) // 同報通信=ブロードキャスト
<< tx_retry(0x1) // 再送1回
<< tx_packet_delay(100,200,20); // 送信時遅延100-200msの間に送信、再送間隔20ms
// 送信データの指定(アプリケーションごとに決める)
pack_bytes(pkt.get_payload()
, make_pair("SCRT", 4) // 4文字識別子
, uint32_t(millis()) // タイムスタンプ
);
// 送信要求を行う
return pkt.transmit();
} else {
// .prepare_tx_packet() 時点で失敗している(送信キューが一杯)
Serial << "TX QUEUE is FULL" << mwx::crlf;
return MWX_APIRET(false, 0);
}
}

送信要求を行う最小限の手続きです。

この関数を抜けた時点では、まだ要求は実行されていません。しばらく待つ必要があります。この例では100-200msの送信開始の遅延を設定しているため、送信が開始されるのは早くて100ms後です。

on_tx_comp()

void on_tx_comp(mwx::packet_ev_tx& ev, bool_t &b_handled) {
Serial << int(millis()) << ":tx completed!"
<< format("(id=%d, stat=%d)", ev.u8CbId, ev.bStatus) << mwx::crlf;
tx_busy = false; // clear tx busy flag.
}

送信完了時に呼び出されます。evには送信IDと完了ステータスが含まれます。

on_rx_packet()

void on_rx_packet(packet_rx& rx, bool_t &handled) {
Serial << format("rx from %08x/%d",
rx.get_addr_src_long(), rx.get_addr_src_lid()) << mwx::crlf;
}

パケットを受信したら、送信元のアドレス情報を表示します。