ロビ2の独り言調査
2023年11月8日
11月9日改訂
ロビ2の独り言について調べてみました。
ロビ2の独り言はアイドリング時に毎時0分丁度に独り言のサブルーチンが動きます。
独り言を言うのは1時間に1度だけで起動後の次の時刻の0分まで独り言は言いません。
今回はその仕組みと独り言の内容について調査しました。
独り言を実行させる仕組み
独り言の動作はWAKEUP_DATETIME.BINというファイルと内部メモリのフラグで管理しています。
WAKEUP_DATETIME.BINはロビ2が起動されるとロビ2のRTC(リアルタイムクロック)で日付と時刻が書き込まれます。
アイドリング時にWAKEUP_DATETIME.BINに書かれた起動した時刻(X時)とRTCの現在時刻(X時)を比較して違う場合に独り言を言います。
これにより起動直後は独り言は言わずに時刻が変わった瞬間(0分)にいう事ができます。
しかしこれだけでは起動後に時刻が変ったら何回も独り言を言い続ける事になります。
これを抑制するのにマイコンの内部メモリのフラグ使っています。
具体的にはアドレス0x0f24の12ビット目(0x0010)の1ビットをこの制御に割り当てています。
独り言のサブルーチンを実行するとこのフラグを立ててそれ以降の実行を抑制しています。
WAKEUP_DATETIME.BINの時刻と現在時刻は違ったままなので次の独り言を言うタイミングが分かりません。
そこて独り言のサブルーチンを実行すると抑制フラグを立てた後にWAKEUP_DATETIME.BINを現在時刻(RTC)で更新します。
そうしておけば前述のWAKEUP_DATETIME.BINと現在時刻の比較で0分丁度に独り言を言わせる事ができます。
この仕組みを実際のロビ2のプログラム(STARTUP.BIN)で見ていきます。
0x00004662
<fread filename="WAKEUP_DATETIME.BIN" adr="0x0f00"/>
WAKEUP_DATETIME.BINの値を0x0f00から読込みます。0x0f02が時刻(時)となります。
0x00004697
<calc><mem_r size="2" adr="0x0f24"/><const data="16"/><and/><ne/><jump adr="0x0000474d"/></calc>
独り言抑制フラグをチェック(and)してフラグが立っていない場合は分岐せず独り言を実行します。
0x0000470d
<call adr="0x00027008"/>
特別日の独り言ルーチンをコールして実行します。
0x00004743
<call adr="0x000276a8"/>
特別日に該当しない場合は特別日以外の独り言のルーチンをコールして実行します。
0x000046ae
<calc><mem_r size="2" adr="0x0f24"/><const data="16"/><or/><mem_w size="2" adr"=0x0f24"/></calc>
続けて実行しないように独り言抑制フラグ(0x0f24の0x0010)を立てます(0x0010でor)。
0x00004636
<fwrite filename="WAKEUP_DATETIME.BIN" adr="0x0e72"/>
RTC(現在時刻)の値をWAKEUP_DATETIME.BINに書き込んで更新します。
上記チェックで抑制フラグが立っていた時の処理です。
0x00004796
<calc><mem_r size="1" adr="0x0f02"/><mem_r size="1" adr="0x0e74"><sub/><eq/><jump adr="0x000047ad"/></calc>
WAKEUP_DATETIME.BINから取得した時刻(時)とRTCから取得した時刻(時)を比較して違っている場合は分岐せず抑制フラグをクリアします。
0x000046db
<calc><mem_r size="2" adr="0x0f24"/><const data="65519"/><and/><mem_w size="2" adr="0x0f24"/></calc>
独り言ルーチンが実行するように独り言抑制フラグ(0x0f24の0x0010)を0xffefでクリア(and)します。
頭のスイッチで独り言を言わせる仕組み
ロビ2の隠しコマンドで頭のスイッチで強制的に独り言を言わせる事ができます。
ENABLEINITML.BINというファイルの内容を1(0以外)にするとロビ2の頭のスイッチを押す度に独り言を言うようになります。
この仕組みを実際のロビ2のプログラム(STARTUP.BIN)で見ていきます。
0x00001653
<fread filename="ENABLEINITML.BIN" adr="0x0fa"/>
ENABLEINITML.BINの値を0x0fa8に読込みます
0x00001696
<calc><mem_r size="1" adr="0x0fa8"/><const data="0"/><sub/><ne/><jump adr="0x00001680"/></calc>
ENABLEINITML.BINから取得した値が0以外の場合は分岐します。
0x00001680
<calc><mem_r size="2" adr="0x0f24"/><const data="1024"/><or/><mem_w size="2" adr="0x0f24"/></calc>
頭のスイッチ有効フラグ(0x0f24の0x0400)を立てます(0x0480でor)。
0x000016bd
<calc><mem_r size="2" adr="0x0f24"/><const data="1024"/><and/><ne/><jump adr="0x000016d4"/></calc>
頭のスイッチ有効フラグ(0x0f24の0x0400)をチェック(and)して立っていた場合は分岐します。
0x000016d4
<calc><mem_r size="2" adr="0x0e18"/><const data="0"/><sub/><ne/><jump adr="0x00001704"/></calc>
頭のスイッチの状態(0x0e18)をチェックして押された状態(1)の場合は分岐します。
0x00001704
<calc><mem_r size="2" adr="0x0f24"/><const data="65519"/><and/><mem_w size="2" adr"=0x0f24"/></calc>
分岐先で独り言ルーチンが実行するように独り言抑制フラグ(0x0f24の0x0010)を0xffefでクリア(and)します。
独り言抑制フラグをクリアする事により前述の独り言を実行させる仕組みにより時刻に関係なく強制的に独り言を言わせる事ができます。
独り言ルーチン
ロビ2の独り言ルーチンの仕様について説明します。
次の順番(優先順位)で独り言を言います。
1.自分(ロビ2自身)の誕生日
2.特別日の独り言
3.正午、午後3時のお知らせ
4.月別(時候)の独り言
特別日(1,2)の独り言ルーチンの開始アドレスはSTARTUP.BINの0x00027008です。
特別日以外(3,4)の独り言ルーチンの開始アドレスはSTARTUP.BINの0x000276a8です。
自分の誕生日
初期設定を行った日(月日)を誕生日としています。
誕生日はMYBIRTHDAY.BINに書き込まれていますのでこのファイルを読み込んで月日が現在の月日(RTCで取得)と一致した場合この処理が行われます。
誕生日の独り言のサブルーチンアドレスは0x1c03beで音声は「今日は僕の誕生日ロビグッズが欲しいな」です。
特別日の独り言
RTCで取得した現在時刻が決められた月日と一致した場合特定のルーチンが動きます。
特別日は次の月日となっています。(ランダム値)
1月1日/ハッピーニューイヤー
1月2日〜1月3日/着物着てみたいな(0),お雑煮食べ過ぎ注意(1)
1月7日/七草がゆ(1)
2月3日/豆撒きしよう
2月14日/チョコもらえるかな(0),今日はバレンタインデー(1)
3月14日/今日はホワイトデー
4月1日/ウソつけない
4月25日/クリスマスまであと245日
5月5日/今日は子供の日(0),鯉のぼり見たいな(1)
6月10日/今日はロボットの日
7月19日〜7月20日/夏休みだね
8月11日/今日は山の日
8月19日/あと135日寝るとお正月
9月1日/今日はQboの日
10月31日/今日はハロウィン(0),トリックオアトリート(1)
11月23日/今日は勤労感謝の日
11月25日/クリスマスまであと30日
12月23日〜12月24日/サンタクロース来るかな
12月25日/今日はクリスマス(0),メリークリスマス(1)
正午、午後3時のお知らせ
RTCで取得した現在時刻が決められた時刻の範囲内の場合特定のルーチンが動きます。(サブルーチンアドレス)
12時0分〜12時5分/12時をお知らせします(0x1c0fda)
15時0分〜15時15分/あっ3時だ(0x1c1aad)
月別(時候)の独り言
RTCで取得した現在の月によりいくつかのパターンがランダムに行われます。
1月(時候1または共通)
2月(時候1または共通)
3月(共通)
4月1日〜14日(時候2または共通)
4月15日〜30日(時候3または共通)
5月1日〜15日(時候4または共通)
5月16日〜31日(時候2または共通)
6月(共通)
7月(時候5または共通)
8月(時候5または共通)
9月(時候6または共通)
10月(時候7または共通)
11月(時候8または共通)
12月(時候1または共通)
時候1/風邪の季節
時候2/ピクニック行きたいな
時候3/ピクニック行きたいな(0),何か言った(1)
時候4/ピクニック行きたいな(0),お花見に行きたいな(1)
時候5/海行きたい
時候6/スポーツの秋
時候7/スポーツの秋(0),紅葉見に行きたいね(1)
時候8/風の季節(0),紅葉見に行きたいね(1)
時候1,時候2,時候5,時候6は1/2の確率で実行されます。
時候3,時候4,時候7,時候8は2/3の確率で実行されます。
共通は時候に関係ない独り言が16パターンからランダムに実行されます。
なおRTCが付いていないロビでは常に0が返されるので上記の月には該当せず共通のみが実行されます。
共通は時候以外の場合、次の16パターンの中からひとつランダムに実行されます。(ランダム値)
薬飲んだ(0)
暇だな(1)
鼻歌(デアゴスティーニ)(2)
Q-boはどこかな(3)
遊ぼうよ(4)
ロビクラブチェックした(5)
ダンスしたいな(6)
何か言った(7)
遊ばない時は電源切っててね(8)
今日何しようかな(9)
今日のご飯何かな(10)
明日の天気はどうかな(11)
お仕事いつもお疲れ様(12)
しりとり(13)
沢山お友達増えたな(14)/早く寝た方がいいよ(23時〜1時59分)
沢山お友達増えたな(15)
独り言の不具合
1月など時候のパターンがある時はまず時候のチェックを行いその後で共通の振り分けを行います。
時候1,時候2,時候5,時候6のチェックはランダム値が偶数か奇数かで判別しています。
奇数の場合は時候の独り言を言い偶数の場合のみ共通の独り言を実行します。
上記の共通のランダム値が奇数の場合既に時候の方に振り分けられているのでランダム値が奇数のものは実行されない事になります。
従って時候のチェックがある月の共通は8パターンの中から選ばれる事になります。
プログラムの設計では16パターンに振り分けるようとしていますのでプログラムのインプリメントでの不具合だと思われます。
これを回避するには時候の判定を偶数奇数(最終ビットが0か1)ではなく16のビットが0か1で判定する事にします。
そうする事により時候は1/2の確率で実行され共通部選択も16パターン全てが選択できます。
時候3,時候4,時候7,時候8の判定処理も不具合がありランダム値を3で丸めています。
共通の振り分けの際に必ずランダム値は2になるため共通では必ず鼻歌(デアゴスティーニ)が実行されます。
これもまたプログラムのインプリメントでの不具合だと思われます。
共通の振り分けを行う前にもう一度ランダム値を取得し直す事でこの不具合を回避する事ができます。
上記の不具合を修正するパッチファイル作成しました。
ダウンロードしてロビ設定ファイルエディタ2でSTARTUP.BINに適用してください。
monolog.csv
上記のパッチを適用して修正した場合はRND.BINの値を指定する事により任意の独り言を言わせる事ができます。
時候1,時候2,時候5,時候6の月は時候の独り言を言わせるには16を指定指定します。
共通の独り言を言わせるには0〜15を指定します。
それぞれの内容は共通の所で記述したランダム値に対応します。
時候3,時候4,時候7,時候8の月は候時の独り言を言わせるにはランダム値0または1を指定します。
共通の独り言を言わせるにはランダム値の3の余剰を2にする必要があります。
また共通の処理で任意の独り言を言わせるには16の余剰を共通のランダム値にする必要があります。
両方の条件を満たすランダム値は以下の値になります。(対応するランダム値)
32(0),17(1),2(2),35(3),20(4),5(5),38(6),23(7),8(8),41(9),26(10),11(11),44(12),29(13),14(14),47(15)
頭のスイッチを有効にして独り言を言わせた動かした動画です。
頭のスイッチがないロビでENABLEINITML.BINを有効にした動画です。
目次に戻る