まどかの 日記

[2001/10/13〜2001/10/21の日記]
[2001/10/22〜2001/10/28の日記]
[2001/10/29〜2001/11/04の日記]
[2001/11/05〜2001/11/11の日記]
[2001/11/12〜2001/11/18の日記]
[2001/11/19〜2001/11/25の日記]
[2001/11/26〜2001/12/02の日記]
[2001/12/03〜2001/12/09の日記]
[2001/12/10〜2001/12/16の日記]
[2001/12/17〜2001/12/23の日記]
[2001/12/24〜2001/12/30の日記]
[2001/12/31〜2002/01/06の日記]

0093
2002/01/13 ()
 良い買い物をしました 
 今日は夕方まで、彼女とお寿司を食べにいったり、買って来たマンガを読んでマッタリした後、名古屋のJRタワーズ内にある東急ハンズに暖房器具を買いに行きました。

 で、石油ストーブは石油買いに行く暇がないし、電気ストーブは電気代かかるわで、どうしようかと考えていたのですが、東急ハンズにある、扇風機型の遠赤外線ヒーター(ハロゲンヒーターっていうそうです)を買うことにしました。
 これは、いわゆるコタツの暖かい光を扇風機みたいに放射する感じの器具で、弱でもすごく暖かいし、2秒で即暖なのですごく便利。しかも、電気代は弱で1時間7.5円。これは、安いです。他の電気ストーブとかだど、1時間23円とかなので、約3分の1省電力。いい感じ。
 首振り機能もあるので、お部屋の中もあったかに(^^;
 これで、手だけ冷たいということもなくなって快適に。はぁ〜良かった。


 はい、今日のMM音楽館ですが、やっとファイルを送信して保存するところまでできました。
 あとは、赤外線通信の時に、電池の電圧を調べて、低いようなら警告するというのと付け加えるくらいです。
 けど、ファイルのサイズによって通信のタイミングが合わないという現象が出てきて困っています。
 
 赤外線の通信には通信手順にもよりますが、今のやり方では、何かを受け取って返事を返すタイミングが、向こうが何かを送って返事を待つタイミングとうまく合わないと、通信できないんです。
 おそらく、データの頭か終わりがちゃんと見つけられないからでしょうね。カーネルの赤外線通信ルーチンがどのようなやり方をしているのかは知りませんが、受信の場合、受信APIであるpceIRStartRxを実行してから、一定の期間の間に、データが送られてこないと、その後いくら再送しても通信に失敗しているような感じです。

 なので、通信のタイミングは重要で、送信側と受信側はタイミングを合わせる必要があって、ファイルのサイズが異なる場合に、通信のタイミングが合わないのは、ファイルを受け取るバッファを確保するmemcpyやコピーするmemcpyの処理時間が異なるからで、固定のタイミングにあわせたウエイトの取り方では、上手くいかないことが今日わかりました。
 わかったというか、まだ推測ですが(^^; たぶんそう。

 現在通信手順としては、

<送信側>
 1.「送信データサイズ」を送信
 2.「送信データサイズ」送信完了待ち
 3.「受信OK」受信完了待ち
 4.「送信OK」送信
 5.「送信OK」送信完了待ち
 6.「送信ファイル名」送信
 7.「送信ファイル名」送信完了待ち
 8.「送信要求」受信完了待ち
 9.「データ」送信
10.「データ」送信完了待ち
11.「受信終了」が来るまで8へ
12.「受信終了」が来たら送信終了  

<受信側>
 1.「送信データサイズ」受信
 2.「送信データサイズ」受信完了待ち
 3.「受信OK」送信
 4.「受信OK」送信完了待ち
 5.「送信OK」受信完了待ち
 6.「送信ファイル名要求」送信
 7.「送信ファイル名要求」送信完了待ち
 8.「送信ファイル名」受信完了待ち
 9.「送信要求」送信
10.「送信要求」送信完了待ち
11.「データ受信」完了待ち
12.データを全て受信したら、「受信終了」を送信して終了

 というような感じで、ファイルサイズが違うと、受信側の8から9に移る間の時間がpceHeapAllocの処理時間が違うことにより(おそらく)ずれてしまいます。これが今悩んでいる問題ね。
 
 と、今通信手順を書いてみて気づいたのですが、「受信OK」と「送信OK」のやり取りって、別にファイル名を送受信してからでもいいよねぇ。「ファイル名」の送受信は、後からこの位置に入れたものだから、こんなになっちゃってるけど、ファイル名を送信した後、送信側は何回か「受信OK」を待って、受信側がメモリの確保をし終えてから「受信OK」を送信すれば、後の通信は固定サイズの通信なので、ここさえ上手くいけば、後はちゃんと上手く出来るはず。

 うむ、これを明日にでもやってみようかな。

 ということで、今日はこれまで。おやすみなさい。

0092
2002/01/12 ()
 むむぅ。うまくいかないもんだなぁ。 
 今日は、たっぷり寝て、赤外線通信にレジューム機能をつけることにしました。

 けど、レジューム機能をつける前に、今までダミーデータの通信だったのをちゃんとしたデータを送るように変えました。
 すると、処理がちょっと増えて、通信のタイミングがずれてしまったみたいで、また上手く通信できなくなってしまいました(j−j
 WindowsパソコンのCPUはP/ECEに比べてると、恐ろしく速いので、処理の1つや2つ増えたところで、処理の時間にそんなに変わりはないのですが、P/ECEは24MHzなので、memcpyのコピーサイズが変わっただけでも、結構な違いが出てしまうようです。
 なので、最適なタイミングで通信するように、ウエイトを調整しないとダメなんだよね。

 今は、P/ECEのハードウェアが統一されているので、実機で実験した時のウエイトでやればOKだけど、Windowsみたいにマシン環境が異なる場合は、どうやればいいんだろうね。
 赤外線通信は有線じゃないので、毎回の通信が全然保証されていません、毎回データが頭から来るとは限らないです。しかも、P/ECEの場合、うまいタイミングでpceIRStartRxを呼んでやらないと、1回pceIRStartRxを呼んで、後は受信待ちループとかにしてると、全然反応してくれません(j−j
 もしかしたら、ずーっと待ってて、送信側も再送しつづけていればうまくいくのかもしれませんが、今のところそうではないようです。

 できれば、H8でのシリアル通信みたいに、1バイト受信したら受信割り込みがかかって、バッファにあるデータを全部蓄積してからデータの解析をするというやり方が出来れば、確実なんですがねぇ。
 カーネルのソースから改造すれば、そういうことも出来るかと思いますが、ちょっと難しいかな(^^;


 で、なんとかレジューム機能も実装して、通信のタイミングを調節したのですが、ファイルのサイズによって上手くいかないことがあるんです。処理的にはファイルのサイズが違ってても、データの通信回数は変わるけど、各処理の処理時間は変わらないはずなんだけどなぁ。

 そんなこんなでちまちまタイミングを調節して、ちゃんとできるようになったけど、今やったら、上手くいかなかったり。よくわからん。何が違うのだね。ふぅ。

 結局、いろいろ工夫して、毎回のデータ転送量が14バイトになって、秒間3転送くらい出来るようになったから、速度としては、秒間42バイト程でしょうか。だいぶ速くなったんだけど、信頼性がめちゃくちゃ低いので、使い物になりません。しくしく(j−j

 ちうところで、今日はこれで終わり。
 また明日タイミングを調節しなおすのと、ウエイトの調節以外で、上手くいく方法はないかを検討してみます。
 
 それでは、おやすみなさい。

0091
2002/01/11 ()
 今日は寝ました 
 今日は、明日から3連休ということもあって、今までの睡眠不足を取り戻すべく、何もせずに寝ることにします。

 今日仕事を終えて帰る前に、社員のみんなに赤外線通信のデモをやったのですが、なかなか通信が成功してくれなかったので、困りました。
 上手くいかない原因は電池の電圧が低いということでした。電圧が1.2V以下になると、上手く通信できないようです。

 うーむ、これはちょっとやっかいですよね。通信する前に電池の電圧を調べて、一定の電圧以下なら、警告を出すようにしないといけないね。

 というわけで、明日はレジューム機能をつけることにしよう。
 では、今日はこのくらいで、おやすみなさい。

0090
2002/01/10 ()
 やっとまともになってきました(^^; 
 はい、今日は名古屋の会社での作業でした。なんか、出向先より名古屋の方が、会社の雰囲気が性に合っているせいか、時間が経つのが早く感じます。
 まあ、出向先では結構暇なことが多くて、いつも仕事を探しているような状態なのですが、名古屋の会社では、自分がメインの仕事をする(というか自分ひとりでアプリケーションを開発することが多い)ので、やることがいっぱいあって、時間がすぐ過ぎます。やっぱり自分が選んで入った会社の方が良いよね(^^;

 で、赤外線通信の続きなのですが、やっとなんとかまともに通信できるようになってきました。けど、まだまだ通信エラーが発生する確率が高いので、レジューム機能をつけて、途中からやり直せるようにしないと、大きなファイルは送れません。

 今日まででわかった通信のコツは、

 1.pceAppProcの周期は100ミリくらい。
 2.送信・受信は各フェーズで1回のみ。
 3.1度CRCエラーが起きたなどで受信に失敗した場合、次回の受信に成功する確率は極めて低いため、エラーになった場合は、早々にタイムアウトで抜けて、最初からやり直すのが吉。
 この、エラーからの復帰が難しいのでレジューム機能は必須だね。

 という3つ。
 いちばん重いのは3つめの現象で、理由はわからないが、あるデータを受信してエラーになった場合、もう一度pceIRStartRxで受信処理をやりなおしても、その後のpceIRGetStatがいつまでたっても0を返さないので、pceIRStopでいったん赤外線通信処理をハード的にストップさせてから、やり直さないと、上手くいかない。

 おや? ということは、受信をやり直すときはpceIRStopをしてからやればいいのかな? 今日はもう遅いので、続きはまた明日になるけど、試してみようかな。

 でも、やり直してもしばらくはちゃんと受信しない場合はが多いから、結局一緒かな。
 ようはタイミングの問題のようです。うまいこと一定の間隔で送受信を繰り返し、パケットの区切りがちゃんとなるようにしないとダメな感じ。

 赤外線通信をやっているファームの方で、何をみてパケットの先頭を見つけているのかはわかりませんが、ここの部分の設計がへぼいと、エラーからの復帰が極めて難しくなります。というのを、私も仕事で232Cの通信をするファームを書いたことがあるので、よくわかっているつもりです。
 なので、通信の途中でなんとか続けようとするよりも、初めからやり直して、途中から再開するレジューム機能をつけた方がうまくいくと考えています。

 今の状態だと、秒間20バイトのスピードで通信できています。ビットで表すと160bpsになるね。遅っ(^^;
 けど、この20バイトというのは、1秒間に転送されるファイルのデータ部分のことなので、実際の通信速度はもうちょっと速いです。
 という感じで、約1kbのファイルが50秒程で送れる計算になります。上手くいけばですが(^^; 1kbに1分かかると思った方が、わかりやすいかな。やっぱり結構かかるね。1分で意外と長いし。その間、P/ECEは位置を固定しておかないとだめだし。机とかに置いて通信するのがベターでしょうね。私は、手で持ちながらやってますが(^^;
 
 今日は、部屋に戻って、一度仮眠してから始めたので、いつもより頭がスッキリしてていい感じです。
 この後また寝て、仕事に行きます。

 明日は、ファイル名とファイルサイズで同じファイルということをチェックして、データの転送を途中から再開する、レジューム機能の実装に取り掛かりたいです。
 今は、最初にファイルサイズを送信して、にファイル名は最後に送信するようにしていますが、これを、最初にファイル名・ファイルサイズの順番で送信して、チェックをするように変更する必要があります。
 
 まだ、データはダミーなのでファイルに保存もしていませんが、順調に開発が進んでいる感じです(^^;
 あ、ファイルサイズを見て、保存できるかどうかのチェックもいるなぁ。むぅ。ま、ゆっくり考えるとしよう。

 というわけで、今日はここまで。明日がんばって仕事をしたら、土曜日で休みなので、この休日中にはなんとか仕上げたいなぁ。と、その前に、休日ができるように仕事の方をがんばらないとね(^^; 納期が迫っているもので……

 それでは、おやすみなさい。

0089
2002/01/09 ()
 むぅ。うまくいかないなぁ。 
 今日は、早めに帰れたので、赤外線の続きをやりました。

 けど、やっぱりうまくいかないなぁ。ま、うまくいくときもあるんだけど、通信の信頼性が驚くほど低い。
 まあ、信頼性は通信手順の改善でなんとかなると思っているので、うまく通信できる手順をじっくり考えよう。

  受信と送信のタイミングが上手くかみ合わないので、送信したらしばらくは送信し続けて、受信は正常に受信するまで受信を繰り返すことが必要だなぁ。

 送信側は、例えば10回くらい連続で送信しつづけて、返信を何回か待って、ちゃんと返信が来なければ、また再送信を繰り返し、このやり取りが同じフェーズで行われているのなら、リトライ回数で見て、最初からやり直すとかね。
 
 ま、とりあえず通信は出来るみたいなので、このまま精度を上げていくだけです。
 思ったより時間がかかりそうだけど、今月中にはなんとか仕上げたいね。

 というわけで、今日はここまで。
 おやすみなさい。

0088
2002/01/08 ()
 いきなりつまづきました赤外線(^^; 
 えー、今日は、出向先での作業で、それは、まあ普通に仕事を終えて、やりたくてうずうずしてた赤外線通信の実装を早速やってみました。

 で、がんばってとりあえずの仕様を実装して試してみたところ、全然ダメー(j−j

 昨日考えたプロトコルで、ファイル名を送信するのを忘れていたので、それをできるようにデータ長を拡張した、1パケット20バイトで、データ部としては、10バイトでファイル名は最大14バイト。

 という風に、ちょっと仕様を変えたものでやってみて、CRCチェックで通信エラーを検出しているのですが、エラーになりまくりです(j−j なんでかなー? 送るバイト数が多いからかなぁ。サンプルは8バイト固定だったし、通信がほとんど出来ない感じだった「おで○」のライブラリも28バイトとか結構多めだったから、パケット長が長いのが問題かなぁ。
 
 でも、ファイル名を送るために、コマンド識別値+最大12文字+CRC4バイトの17バイトが最小構成かなぁ。
 それでも17バイトにもなるんだね。
 8バイトまで小さくしようとすると、ファイル名を4分割して、コマンド識別値+3文字+CRCの8バイトが最小か。あ、データを送るときのオフセット4バイトが要るから、どうがんばっても最小12バイトが限界か。1バイトずつ送信するとすれば、1パケット10バイトになるけど、遅そうだね(^^;
 
 また、エラーが出た後になんかちゃんと通信できなくなる感じ(デバッグできないのであくまでも感じ)なので、そこらへんから詳しく調べないといけないね。

 そうそう、今日通信でハマリそうな現象を見つけました。
 それは、通信の状態を知るために、pceIRGetStatっていうAPIがありまして、通信中は0以外で、通信が完了したら0を返す仕様なんですが、これの初期値(通信も何もしていない初期状態)での値が0じゃないんですよ(^^;
 なんで、状態遷移型の通信フェーズに対応させて、各通信前にはこのpceIRGetStatを調べて、0だったら通信処理をするという風に作っていると、一番最初でいきなり0が返ってこなくて、なにも進まなくなってしまいます。

 というわけで、通信状態の初期化処理として、まずpceIRStartTx(0,0);でダミー送信をしています。こうすると、すぐ通信が終了してpceIRGetStatも0を返してくれるようになります。っていうか、これくらいちゃんと初期化しといてよねぇ(^^; もしくは初期化手段を用意するとか。pceIRInit(void)とかで。

 APIのソースをのぞくと、pceIRGetStatはグローバルにとってある通信用構造体のメンバの送信用もしくは受信用バッファのサイズを返すようで、通信が終了したらそこに0を代入しているようなんです。
 で、初期状態は構造体の内容も不定なので、0じゃない値が入っているわけですね。うむぅ。

 というわけで、明日は現在の通信フェーズの状態を表示させるようにして、ちまちま処理を追っていきたいと思っています。

 今はすぐエラーがでて終わっちゃうけど、エラーがでるということは、なにかしら反応してるってことなので、それだけでも楽しいです(^^; エラーが出たときにBEEP音を鳴らすようにしているので、反応がわかりやすくて面白いです。ああ、楽しい。

 ああああ、早く続きがしたいなぁ。
 明日はノー残業デイなので、早めに帰っちゃおっかなぁ(^^;

 あ、そうそう、今日サウンドドライバの改良をやってもらっている、ある社員さんからメールで、曲の演奏状態を画面に表示するサンプルが届きました。
 これを見る限りでは、鍵盤表示も夢じゃない感じ(^^; これらの曲の状態をリアルタイムで表示する機能は、「お楽しみも〜ど」としてVer.0.8以降で実装する予定です。

 というわけで、今日はおやすみなさい。

0087
2002/01/07 ()
 うぬぬ、赤外線手強し(^^; 
 はい、今日はふつーに仕事してました。

 で、帰りがけに、社長とP/ECEの赤外線サンプルで、どこまで届くか試したりして遊びました(^^;
 どうやら、ちゃんと計ってはいませんが、2・3mは届くようです。すごいね。楽しかったです。

 それで、お部屋に戻って、赤外線のサンプルを見てみたのですが、まかべさんの「FileViewer」では「おで○」のソースから流用したものを使っているようですね。けど、ぱっと見て、複雑ででよく分からなかったので、これは使わないことにします(^^;
 
 また、appフォルダにある「ir」っていうサンプルでは、pceCRC32なる非公開APIを使用しているのを発見!!
 これは、データへのポインタとデータサイズを渡すと、そのデータのCRCコードを返してくれるもの。
 これを使えば、簡単にCRCチェックによる通信エラーが検出できそうだ。というより、「ir」サンプルでは、実際にこれで通信エラーを検出してるしね。

 で、肝心の通信手順なんだけど、とりあえず自分で考えてみるのも勉強と、じっくり考えてわかりやすい手順を使うことにします。

 とりあえず、ぱっと思いついたのが、まず初めに、送信するデータのサイズを送って、受信側主導で、「次はこのオフセットのデータをくれ」という感じで、毎回受信側が要求するデータを送信側が送信するという感じ。
 
 手順を簡単に書くとこんな感じ。

<送信側>
 1.送信データサイズを送信
 2.返信を待つ
 3.タイムアウトになったら1へ
 4.返信があったので送信OKを送る
 5.送信要求を待つ
 6.タイムアウトになったら送信リトライ
 7.要求されたデータを送信
 8.受信終了が送られてくるまで、5へ
 
 受信エラーが出たら、その状態を繰り返します
 タイムアウトが何回も続いたら1へ

<受信側>
 1.送信データサイズが送られてくるまで待つ
 2.強制キャンセルされるまで1へ
 3.送信データサイズが送られてきたら、返信
 4.送信OKが来るまで待つ
 5.タイムアウトになったら3へ
 6.送信要求を送る
 7.データを待つ
 8.タイムアウトになったら6へ
 9.全てのデータを受信するまで6へ
 10.データを受信し終わったら、受信終了を送る
 
 同じ状態で何回かタイムアウトになったら1へ
 送信データサイズが送られてきたら、3へ
 受信エラーが出たら、その状態を繰り返します

 
 パケットは14バイト固定で、先頭1バイトが固定文字、2バイト目がコマンド識別値、次の8バイトがデータ、最後の4バイトがCRCコード。
 
バイト位置 2〜9 10〜13
内容 固定文字 コマンド識別値 データ CRC
 
 こんな感じで。CRCコードは、固定文字からデータまでの10バイトのCRCです。

 で、コマンドは、こんな感じ。

 
コマンド
識別値
コマンド名 データ部の内容
送信データ
サイズ
DWORD型の数値でファイルのサイズを表す
残り4バイトは0固定
受信OK 8バイトはダミー
送信OK 8バイトはダミー
送信要求 前4バイトはDWORD型の数値で、オフセットを表す
残り4バイトは0固定
送信データ 前4バイトはDWORD型の数値でオフセット値
残りBYTE型4バイトがデータ
受信終了 8バイトはダミー

 だいぶ細かいところをはしょってますが、上手くいくといいな(^o^;

 というプロトコルを考えたところで今日は終わり。
 コマンドはダミーが多くて無駄が多い感じもしますが、とりあえずこれでやってみます。
 ダミーでもCRCでチェックするからエラーチェックは大丈夫かな。でも、これだと、毎回4バイトしか送れないからちょっと遅いかも。遅かったらデータ長を増やします。

 それでは、おやすみなさい。