ちょっとTea Time!? パラレル−SPI変換回路を考える。 2020.10.2

 CPM68K次男にはIOボードをとりつけて128*64DOTのグラフィック液晶もつないでいます。
ただグラフィックにしてはやや貧弱で、どちらかといえばキャラクターを表示するためにつけたものです。
6×8フォントなら21文字×8行が表示できますので結構な情報量です。
でも、やぱりもうちょっとグラフィックも扱えたらいいな〜と思うことしばしばです。

 そこで、以前に色々と試しに買ってみた中からTFTの480×320DOTの液晶モジュールも接続できるように接続コネクタを新設しました。
(※Tea Timeのものとは異なり、コネクタが一列になっているタイプのものです)。

先の128×64のLCDはGPIOに接続していましたが、それではデータの転送速度が遅くなりそうなので、MC68000のデータバス
に直接的に接続するようにしています。

 このサイズになると128×64のLCDに比べると、画素数は約19倍になりますので多くの情報が表示できます。
でも、LCD全体のサイズにはあまりかわらないので、必然的にドットが小さくなりますので老眼の進む目には厳しいものがあります。
6×8フォントなら、80文字×40行で表示できるのでモニターの代わりになりますが・・・・、
虫眼鏡がいりそうで、ちょっと無理です(笑。


最初にIO基板にとりつけていた液晶(128×64)です。ちょっと解像度としては寂しいです。



480×320のLCDがとりつけられるように、コネクタを新設しました。MC68000のバス直結です。


サイズ的にはほとんど128×64と変わりません。取り付けたLCDはRM68140というドライバのものです。


解像度は高くなりました。表示速度はまあまあです。でも、文字が小さいなあ〜。

よくこれで動くなあ〜。

使用したLCDは4線式のタッチパネル付きのものです。4線式なので他の端子と低抵抗でつながっているものがあるので、
そこへの信号の供給はできるだけ低インピーダンスで駆動すべきなのですが、そんなこといっても駆動するのはロジックICしかありません。
案の状というべきか、タッチパネルに関連するピンの信号は他のピンの影響を受けて、無茶苦茶汚い波形になっています。
よくまあ、これで動くな〜という気もしますが、これでも動くのがディジタルのいいところなのでしょう。LOWレベル、HIGHレベルが仕様
を満足していればいいわけですからね。


タッチパネルに関連する端子の信号はものすごく乱れています。


タッチパネル以外の端子信号は比較的綺麗です。オーバ、アンダーシュートが大きいから
ダンピング抵抗入れたほうがいいかな〜。


データ転送速度は約1.4us/byte

当初から懸念していたのは表示速度です。それについてもLCDをバス直結にしたためか比較的ストレスなく動くようです。
そこで、データの転送速度を調べてみました。画面の全クリアーを100回おこなったところ約43秒かかりました。
1画面の消去は0.43秒ですね。このくらいならOKです。ちなみに、1画面のクリアーには1ドットづつのすべての画面で
データを送出する必要があります。1ドットは16bitのカラー情報からなりますので、2バイトが1ドットです。
送出しなければならないデータ量は

全画面消去に必要な送出データ量 480×320×2=307kバイト

になります。それを100回繰り返して43秒ですから、1バイトあたりのデータ転送には約1.4usかかっていることになります。

 つかっているCPM68K次男のCPU速度は40MHz(CPUは16MHzなので2.5倍のオーバクロック)ですから、約56クロックです。
ループに必要な命令等も含めると、まあ妥当な線でしょう。MC68000では大体1つの命令の実行には10クロック程度かかりますから、
比較的良好なコードが生成されているようです。

CPM80(Z80)3号機にもグラフィックLCDを使いたい!

CPM68K次男に高分解能の液晶が乗ったことなので、ついでもCPM80(Z80)3号機にも搭載することを考えてみました。
丁度、手元にすこし小さいですが320×240ドットの液晶があります。でも、問題はSPI(シリアル通信)専用ということです。

CPM80のGPIOにSPIをつかって接続したら、いったいどのくらいの時間がかかるか試算してみました。

ソフトSPIだと使い物にならない・・・
 まず、CPM80のC言語ではGPIOに1回データを送出するのにおよそ10usかかります。CPM80のクロックは20MHzで動かしているので、
1クロック50nSですから200クロックを要していることになります。8080のOUT命令は8クロックですから、かなり冗長なクロック
を要しています。これは8080の命令に問題があるわけで、8080の命令ではOUT命令を出力するアドレスはプログラム上に記述しなければ
なりません。アドレスをレジスタ渡しできれば簡単なのですが、8080にはその機能はありません(Z80にはあります。
ただしZ80の命令をつかうCPM80としての互換性が保てなくなります。
 コンパイラはOUT命令をコンパイルすると、命令コードとアドレスをメモリー上に書き込んで、そこを実行するという手間のかかった
コードを生成せざるをえません。これが時間がかかる元凶です。

 そこでシリアルで送るとなると1ビット送るのに少なくとも3回のOUT命令が必要です(データ送出、クロックパルスHIGH、クロックパルスLOWの3回)。
これが8回で1バイトですから、1バイトで24回のOUT命令が必要になります。
 で、1つのOUT命令で10uSかかるとすると、320×240の液晶画面を全消去する時間は最短で

 全面消去(最速) 320×240×2×8×3=約37秒

となります。ただし、実際にはループを回す処理などを含めると、その2倍程度はかかるとみたほうがいいので、早くても1画面消去
で1分以上はかかることになります。それって、たぶん我慢できない速度です。

高速化のために
 LCDへのデータ転送速度を早くするためにも、CPM80とのインターフェイスはパラレルで行って、その先のSPI通信については
ハードウエアで出来ないかな〜と考えることにしました。SPIからパラレルに変換するのは、シフトレジスタがあれば簡単にできますが、
パラレルデータをSPIに変換するのはちょっと工夫が必要です。この変換は、あまりネットにもでていないようです。
 この変換に何が必要かといえば、パラレルデータをSPIに変換するために外部クロックの供給が必要です。またこのクロックを
SPIとする場合には、1バイト分のデータ送出したらクロック止める必要があります。すなわち1バイトである8クロックを
カウンとする機能も必要になります。このあたりが、すこし面倒なところでしょう。
 というかパラレルをSPIシリアルに変換する動機なんて、ほとんどないというのが実体なんでしょうね。
 
こんな回路になるかな?
 ということで、まずは簡単にパラレルーSPIの変換回路を考えてみました。8ビットのデータを選択するために4ビットのデータセレクタを
2個もっている74153を使いました(これならもっている)。本来はシフトレジスタがあれば、もっと簡単になったかもしれません。
しかし、まずは身の回りにある部品だけで、出来る回路となるとこうなっちゃいました。全体で7個のロジックがICが必要です。
もっとも、シフトレジスタがあったとしても、ICの個数が2〜3個へっただけかもです。


パラレル信号をSPIに変換する回路を考えてみました。

実際に作る気になる速度になるかな?

一応回路は描いてみたものの、実際に作ってみてあまりも想定した速度と違っていたら(勿論遅い)、なんかがっかりしそうなので、
念のために、ダミープログラムを組んでみてどのくらいの速度になりそうか実測です。
結果としては、OUT関数をつかった場合の全画面消去の時間は約2.5秒です。う〜ん、微妙だなあ〜。我慢できるかなあ〜。
そういえば、昔のPC8801のときもグラフィック画面の消去って結構時間がかかったような気もするし、こんなもんかなあ〜。

ちなみに、OUT関数をつかわずにメモリーマップドIOとした場合も時間を測定してみましたが、こちらは約1.6秒です。
まあ、早くはなりましたが・・・・これを実現するにはメモリーアドレスのデコードを新たに追加しないと駄目なんですよね〜。
そこまで、手を加えても1.6秒かあ〜。んんん・・・・モチベーションがあがらない・・・・。


全画面消去 約2.5秒 out関数をつかった場合
我慢できるか出来ないか、微妙な時間だなあ〜。


全画面消去 約1.6秒 メモリーマップドIOとした場合
だいぶ速くなったけど、さらにハードを追加しないとだめだしなあ〜、
そこまでやるかなあ〜??

なんか企画倒れの感が・・・・

ここまで検討してきて、得られる結果にちょっと寂しいものを感じはじめました。
どうしようかなあ〜??? とりあえず休日前夜なので時間には余裕があるし、
ビールでも飲めばやる気がでてくるかもしれません(笑。

ちょっと思考を変えて

ロジックICをつかった変換回路だと高速なSPI変換ができますが、作るのが面倒です。
SPI変換の速度を落としてもよいのなら、PICをつかったソフトロジックで構築できるかもしれません。
おそらく、SPIのクロック速度は数100kHzまで低下しそうですが、はるかに簡単です。
PICのH/W-SPIをつかえば1MHzくらいまで稼げるかな?いづれにしても、
たぶんPICをつかうならPIC1個とロジック1個程度でできるでしょう。この際、PICのH/W-SPIを調べてみようかな?
しかし、LCDとCPM80間のインターフェイスに、メインのZ80(20MHz)より高性能なCPUをつかうのってどうよ!
って気もしてきました。

 んん・・・そろそろ酔っ払いモードに突入だあ〜。また明日考えよ。


PICでのH/W-SPIの速度は?
 ちょっと調べてみました。SPIクロック速度はシステムクロックの1/4あるいは1/16、1/64が選べます。
もっと低速ならタイマーをつかうことができるので、微調整ができるのですがここではスピード優先です。
で、PICの動作周波数を64MHzにして、SPIを1/4システムクロックに設定すると16MHzです。
ただし、この場合はクロックが早すぎてLCDのドライバの仕様を満足できません。
(ドライバ側のHIGHパルス幅は最低でも60nsですが、16MHzだと31nsしかない)。

そこで、システムクロックの1/16の4MHzが適切な値になります。このときにHIGHパルス幅は125nsくらいになるので
結構余裕がでてきます。

PICでのSPI信号です(上:DATA。下:SCK)

PICだとなんとなく微妙に遅い・・・・

SPIのクロックが4MHzだと1バイト送るのに、2usかかります。なんか微妙に遅いなあ〜。
MC68Kでのバイト転送で1.4us/バイトだからなあ〜。
それに、PICでその他のソフト処理を含めると、おそらく4usはかかります。この値は
CPM80からデータが送られる間隔がOUT関数で約9us、ダイレクトメモリだと6us程度なので
次のデータが送られる前にはSPIでデータを送信しきっているので問題はありません。

しかし、あらためてコンパイルされたアセンブラをみていると、かなり短縮できそうです。
すくなくとも全画面消去なんかは1/2〜1/4くらいにはなりそうです。となると、すぐにSPIでは
間に合わなくなります。

やっぱりSPI変換はロジックによる外付けH/Wが必要かなあ〜??

もうちょっと考えよ!


もとい! 2020.10.4

もともとはSPIで動作する320×240のLCDをつなぐつもりでいましたが、部品箱をあさっていたら
ARDUINO用の480×320のLCDがでてきました。ARDUINO用なのでピン配置がインチピッチから
ずれているのがあるので、蛇の目基板とは相性がよくありませんが、乗せようとすれば乗らないわけでは
ありません。すこしピンをまげてやれば、なんとか半田付けできます。

 ということで、より大きなLCDがでてきたのでこれをつかうことにしました。これはSPIではなくてパラレル転送のみ
なので、結局もともとの目的から完全に逸脱してしまいました。


ARDUINO用の液晶のピンはピッチがインチでないところがあるので、取り付けがちょっといびつになります。


搭載したのは、CPM80の3号機です。


480×320の液晶をつかうことにしたので、結局のところIO基板から作り直すことにしました。
まあ、大した配線量ではなりませんから2〜3時間もあれば作れます。休日の作業にはもってこいです。

遅〜!!!

配線が終わったのでえ、サンプルプログラムを作成して早速動かしてみました。
まずは画面消去についてですが、なんと1画面の消去に10秒もかかってしまいました。
まさに劇場の緞帳が下りるがごとくです。
 さらに16×16ドットの文字を書いたら、1行(30文字)書くのに1秒近くかかってしまいす。

とんでもなく遅いです。

 コンパイルで生成されたアセンブラをみていると、ものすごく冗長なところがあります。
さらに、やたらめったらサブルーチンが呼ばれています。何をしているのだろう?
 そもそもZ80(8080)自体がC言語の実行には適したアーキテクチャーになっていないので、
コンパイラが困憊(こんぱい)しているのでしょう(一応、駄洒落のつもり(笑。

いつでにしても、単にC言語で書いただけでは遅くて精神的によくありません。
時間のかかるところはアセンブラに書き換えたほうが良さそうです。


画面消去の速度は10秒くらいかかります。




16×16のフォントを1行書くには約1秒かかります。遅〜!!!

まあ、いまより遅くなることはないので、どこまで速くなるかを楽しみにして、プログラムを改善していきましょう。

#今回はTeaTimeのタイトルどおりにいかなかったですね。

エピローグ? 2020.10.5

流石に描画速度が遅くて、こまままでは使い物にならないので、主要なルーチンをアセンブラで組みました。
いや〜超超久しぶりのアセンブラです。さらにZ80ではなく8080のニーモニックなので、色々と調べながらの作業です。
でもその甲斐があって、かなり速くなりました。

 画面消去  約10秒   → 約0.5秒(約20倍)
 文字描画  1行/秒  → 1画面/約0.8秒(約40倍)

ここまで速度があがると、ストレスも小さいので、なにかアプリケーションを書きたくなってします。
しかし、アセンブラで組んでこの速度なので、ほぼ限界値です。やはり20MHzで動いているとはいえ、Z80の限界でしょう。

調子にのって・・・・
もっと高画素のLCDを入手しました。800×480ドットです。ここまでくれば、往年のPC9801の解像度(640×400)を上回ります。
ただし、サイズは3.97インチです。480×320が3.5インチなのであまり大きさは変わりませんが、画素数は2倍以上になっているので
当然のことながら、どんどん文字が小さくなってしまいます。ということは、視認性を上げるには文字ドットを増大させる必要があるのですが、
そうなると高画素になったメリットがでなくなってしまいます。まあ、細かく図形が描画できるメリットはありますが・・・・それに対応するには
やっぱりCPUのパワー不足は否めませんン。さてさて、どのCPUに搭載しようかな〜。
 また、この800×480ドットはデータバスが標準で16ビットですが8ビットにも変更できます。ただし、8ビットに変更するとどんなに短いコードでも
2回のバスアクセスが必要になりますので、さらに無駄な転送が生じてしまいます(単純に倍では済まなくて3〜4倍程度時間がかかる場合もある)。
ということで、高速なCPUでないとまともに動かせそうにないです。 さてさて、どうなることやら。またTea Timeで検討です。


800×480のLCDも入手しました。まずはPICで動かしています。


大きはほとんど同じ。どちらも16ドットのフォントを表示させましたが、800×480だと小さいです。


(おしまい)