P/ECE研究室〜S1C33分室



* Mon Jun 27 18:33:00 JST 2002 Naoyuki Sawa




今回も「アプリケーションを実行するたびに画面の濃度が変わってしまう」問題についてです。

昨日、トップページでサンプルソースをご紹介しました通り、一応の解決方法が見つかりました。



解決方法の話に入る前に、すこし前回の補足を行います。

前回使った濃度バラつき問題再現プログラムに、いくつか修正を加えました。

修正点は次のとおりです:



・ディザを多く含む絵の方が濃度のバラつきがわかりやすい、と書きましたが、

 どうやらそれよりも黒ベタの絵の方が濃度のバラつきがわかりやすいようです。

 というわけで、黒ベタ&左上に操作説明、という画面に変更しました。



・アプリケーションを終了→再実行しなくても、濃度のバラつきを再現できるようにしました。

 −これまで「アプリケーションを実行するたびに」濃度のバラつきが発生する、と書いてきましたが、

  正確には「pceLCDSetOrientation() APIを呼び出すたびに」濃度のバラつきが発生しているのです。

  pceLCDSetOrientation()は、内部でLCDCのリセット処理を行っています。

  どうやらこのリセット処理が上手く行っておらず、濃度のバラつきを引き起こしているようです。

 −pceLCDSetOrientation()が原因なのに、なぜアプリケーション実行のたびに濃度が変わるのでしょうか?

  ほとんどのアプリケーションは、pceLCDSetOrientation()なんか使っていないはずですよね。

  その理由は、アプリケーション開始直前に、カーネル内部でpceLCDSetOrientation(0)が呼ばれるからです。

  前のアプリケーションが画面回転したまま終了した場合、次のアプリケーションも回転したままに

  なってしまったりするのを防ぐためだと思います。

 アプリケーションの終了→再実行をしなくても、pceLCDSetOrientation()を呼べば濃度バラつきが再現できます。

 Aボタンを押すと、pceLCDSetOrientation()を呼ぶようにしてみました。



	以上二点を修正した問題再現プログラムのソースはこちら



問題再現プログラムをコンパイル・実行して、何度かAボタンを押してみてください。 画面の濃度がバラつくことが確認できたでしょうか?
実は、ある条件によって、いくらAボタンを押しても濃度がバラつかないこともあります。 濃度のバラつきが発生しなかったかたは、 「最近P/ECEのリセットボタンを押していませんね?」 いちどP/ECE背面のリセットボタンを押してから、サンプルプログラムを実行してみてください。 今度は濃度のバラつきが発生したと思います。 P/ECEの電源投入後、いちどもリセットボタンを押さなければ、濃度のバラつきは発生しません。 アプリケーションの実行・終了を繰り返したり、何回もpceLCDSetOrientation()を呼び出ししても、 リセットボタンを押さない限りは、濃度のバラつきが発生するようにはならないようです。 なお“電源投入”とは、電池を入れていない状態から、電池を入れるかUSBにつなぐことを指します。 スリープ状態への移行→復帰だけでは、電源投入とは見なされないようです。 実験により、濃度のバラつき問題はリセットボタンに関係があることがわかりました。 ですが、なぜこうなるのかはまだわかっていません。 P/ECE開発環境に入っている回路図を見る限り、リセットボタンとLCDCはまったくつながっていません。 LCDCの立場から見れば、リセットボタンが押されたかどうかなんて、わからないはずなのです。 とすると、リセットボタンが押されたときに実行される、初期化プログラムに問題があるのでしょうか? 電源投入直後は、LCDCも完全な初期状態にあると見なすことができます。 これに対して、リセットボタンを押した場合は、前述の通りLCDCはリセットボタンを感知しませんので、 LCDCはリセット前の状態を引き継いでいて、不安定(?)な状態になっているのかも知れません。 電源投入直後およびリセットボタンが押されたときに実行されるLCDC関連の初期化ルーチンとしては、 InitSPI()とInitLCD()があります。(どちらも lcd.c にあります) これらの初期化プログラムは、LCDCが完全な初期状態(電源投入直後)ならば正しく動きますが、 LCDCが不安定な状態(リセット後の状態)だと正しく初期化できない部分がある・・・のかも知れません。 試しに、電源投入後リセットボタンを押していない状態(濃度のバラつきが発生しない状態)から、 プログラムでリセットベクタ([0xc00000])にジャンプし、InitSPI()とInitLCD()を実行してみました。 その結果、やっぱり、濃度のバラつきが発生するようになりました。 想像ですが、InitSPI()かInitLCD()の処理に、どこか問題があるのではないかと思います。 結論: とりあえず次のような方法で、濃度のバラつき問題を解決することができます。 1.電池を抜いてください。または、USBから外してください。 2.電池を入れてください。または、USBにつないでください。 3.リセットボタンを押さない限り、普通に使っている分には、濃度はバラつきません。 4.もしリセットボタンを押してしまったら、1に戻ってください。
濃度のバラつきが発生するたびに、いちいち電池を抜いて…というのもあんまりなので、プログラムによる対処方法を探ってみます。 前回、「タイミングの問題でコマンドの一部が届いていないのでは…」と予想しましたが、タイミングの問題ではありませんでした。 試しに、初期化手順の各コマンドの前後に、たっぷり1秒程度の待ち時間を入れてみましたが、やはり濃度のバラつきが発生しました。 予想が外れたので、他の手段をいくつか試してみた結果、次のような方法で濃度のバラつきをなくせることがわかりました。 P/ECEカーネルがpceLCDSetOrientation()経由でLCDCの再初期化を行った後、 アプリケーションプログラムからもLCDCを直接操作してもういちど再初期化する ただし一点だけ、pceLCDSetOrientation()による再初期化手順とは、異なる手順を採る必要があります。 昨日、トップページにも書きましたように、 Resetコマンドではなく、RESETB端子を使ってLCDCをリセットする という点です。 RESETB端子を使ってLCDCをリセット・再初期化して、濃度のバラつきをなくすサンプルプログラムはこちら
Aボタンを押すと、先ほどの問題再現プログラムと同じく、pceLCDSetOrientation()を呼び出します。 何度かpceLCDSetOrientation()を呼び出すと、画面の濃度が変わると思います。 画面の濃度が変わったら、Bボタンを押して、LCDCの再初期化を行ってみてください。 Aボタン(pceLCDSetOrientation())は押すたびに濃度がバラつきますが、Bボタンはいつも同じ濃度になります。 これが、正しい画面濃度なのです。 #前回、バラつく濃度の「濃い方が正しい濃度」ではないかと書きましたが、間違いでした。「薄い方が正しい濃度」です。 #濃い方が見易いと思うのですが、まあ濃度のバラつきさえなければ、メニュー画面で好みの濃度に調整可能ですので、良しとしましょう。 サンプルプログラムでBボタンを押したときの再初期化処理(nodo3.c内のlcd_init()とusleep()関数)と同じ手順を、 アプリケーションのpceAppInit()に組み込めば、濃度のバラつき問題は解決できます。 試しに自作プログラムに組み込んでみたところ、確かに濃度のバラつきがなくなりました。
さて、なぜ、Resetコマンドによるリセットではダメで、RESETB端子によるリセットならOKなのでしょうか? 実は、よくわかっていません。 LCDCリセットの手順を、ResetコマンドからRESETB端子に置き換えてみようと考えついたのも、特に根拠はありませんでした。 LCDCのデータシートに、RESETB端子を使ったリセット処理のフローチャートは載っていましたが、 Resetコマンドをつかったリセット処理のフローチャートは載っていなかったから、というだけの理由です。 とりあえずデータシートに載っている確実な方法を採ってみよう…と思ってやってみたら上手くいった、というだけです。 Resetコマンドによるリセットと、RESETB端子によるリセットの違いは、 電源関連のパラメータが初期化されるかどうか、という点にあります。 Resetコマンドによるリセットでは、電源関連のパラメータはリセット前の状態を維持しますが、 RESETB端子によるリセットでは、電源関連のパラメータも含めて完全に電源投入直後の状態に戻ります。 pceLCDSetOrientation()の再初期化手順でも、電源関連のパラメータを全て明示的に設定していますので、 Resetコマンドが電源関連のパラメータを初期状態に戻さなくても関係ないように思えるのですが、 現実には濃度のバラつきが発生してしまっています。 もしかすると、電源関連パラメータ設定は、電源投入直後またはRESETB端子によるリセット直後一度しか許されておらず、 電源関連のパラメータ設定を二回以上行おうとすると、不安定な状態になってしまうのかも知れません・・・ ・・・いや、データシートにはそんなこと書いてないし、そんな変な仕様は考えづらいのですが、他に思いつきませんでした。 しかしよく考えたら、InitSPI()とInitLCD()はちゃんとRESETB端子を使ってLCDCリセットを行っているので、 この想定では、InitSPI()やInitLCD()で画面の濃度が不安定になる理由が説明できなくなってしまいますね。 やっぱり違うなぁ。 というわけで、濃度問題の解決法はわかりましたが、そもそもなぜ濃度のバラつきが発生していたのかは未解決のままです。 濃度バラつきの発生原因などについて情報をお持ちのかた、おられましたら、ぜひ教えてください。よろしくお願いします。 (続きます...)

nsawa@piece-me.org