SSブログ
English Version

Pic24MC68Kマイコン(その7)CP/M-68Kの移植 [68K]

 前回の記事でプリント基板に部品を実装して動作確認ができたことを書きましたが、回路図をまだブログに書いていなかったことに気が付きましたw

 順番が前後してしまいますが回路図は下図になります。自作の回路なのでいつものように使用部品を最小限にするように考慮しました。
 MC68HC000(MC68000のCMOS版)とPIC24FJ64GAを連携させるためには
  • スリーステートバッファ
  • 反転ゲート
  • ANDゲート
が必要だったのですが 3-State Bus Inverter である 74HC368 を使うことでこれらの機能を一つのICで実現しています(ゲート入力とイネーブルピンで論理的にANDしている)。

 スペックの概要としては MC68HC000 が 16MHz で動作(ジャンパーピンで 8MHz に切り替え可能)し、メモリは 512K x 16bit 実装しているので、小ぶりながらなかなかの高スペックです。
 具体的な回路図は下図になります(クリックでPDF表示になります)

Pic24MC68K回路図


 下図がグランドベタ化前の両面のパターン図です。今回は表面実装部品を多用して基板サイズを MC68000 の 64 ピンの DIP サイズにまとめたのでトラックは少々混みあっています。

Pic24MC68Kのパターン(グランドベタ化前)


 グランドベタ化後のトップ面のパターンが下図になります。MC68000チップの下にメモリ(AS6C8016:512K x 16bit)とバッファICなどを実装しています。メモリは 5V 対応の 8M のスタティックRAM で、1カ月ちょっと前に購入したものですが、予備として追加購入しようと通販サイトを見たところ、2倍以上に値上がりしていて驚きました。

Pic24MC68Kのパターン(トップ面)


 ボトム面には PIC と USBシリアル変換用IC(PL2303SA)、USBコネクタ、SDカードコネクタ等を実装しています。USB ケーブルを直に接続できるというのは結構便利です。

Pic24MC68Kのパターン(ボトム面)


 3D 表示の図も貼っておきます。

Pic24MC68Kの 3D 表示(トップ面)


 ボトム面の 3D 表示は下図になります。

Pic24MC68Kの 3D 表示(ボトム面)


 CP/M-68Kは以前 MC68008 を使って自作した Pic24CPM-68K のプリント基板を作った時に移植済みだったので、今回は CP/M-68K の環境を使って割合すんなり移植できました。
 68K は A0 のアドレス線が無く、上位バイトが偶数アドレスで下位バイトにはその次の奇数アドレスが振られている(ビッグエンディアンなのでまっとうな割り振りだと思う)のですが、PIC 側は 16bit に一つのアドレスなのでアドレスの値は MC68K の 1/2 になります。
 更に ワード単位では MC68K と PIC は同じデータですが PIC 内でワードからバイトに変換する際に逆になる(PICはリトルエンディアンなので)ので頭が少し混乱しますw
 SD カードとのインターフェースである SPI はバイト単位でしかアクセスできないので PIC内で上位/下位バイトを交換後、外部メモリをワードアクセスする必要があります。

 PIC 側の PMP機能でバイトイネーブル信号の論理を逆にすれば、PIC 内でのバイト/ワード変換時の並び替えは不要になるのですが、この場合、PIC の上位バイトはメモリの下位バイトに書かれることになり、更に頭が混乱してバグの元になりそうだったので止めましたw

 CP/M-68K を自動起動に設定し、リセットボタンを押下して CP/M-68K が立ち上った際の画面キャプチャが下図になります。

Pic24MC68Kでの CP/M-68K 起動時の画面例


★追記 2022/02/10
 「TRY! CPM-68Kの巻き」のサイトに SD カード上での hello.c のコンパイルに時間が掛かるというようなことが書いてあったので実測してみた結果をメモしておきます。
 因みに、PIC 側のソフトウェアは自作の picle コンパイラで開発しており、SPI 機能を含め、C言語のライブラリは一切使用していません。

compile link total
8 sec13 sec21 sec


★追記 2022/02/19
 今回開発した MC68K のチップサイズと同程度のサイズのプリント基板をイメージし易いように、twitterに投稿した動画付きメッセージを貼っておきます。



★追記 2022/03/18
 Twitterに投稿した動画にプリント基板の写真などを追加して Youtube で公開しました。




[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

ポケコン(G850)ポリラインで動画再生 [ポケコン]

 「ポケコン(G850)高速ライン描画」の記事で高速なライン描画処理ができれば線画画像等の動画を効率よく表示できるのではないかと言うアイディアを書きましたが、少し実験してみたのでメモしておきたいと思います。

 今回の実験のために準備したものは次の通りです。

  1. ポケコン(PC-G850V)用の高速ライン描画処理
     ライン描画ループ内にPset処理を取り込むことでVRAMアドレス計算等を最小限にして想定通りの高速処理ができた(詳細は上記記事内容を参照してください)

  2. 画像ファイルからの輪郭抽出
     ネットで画像ファイルから輪郭を抽出できるPotrace(Transforming bitmaps into vector graphics)というツールを見つけた
     色々なフォーマットで輪郭のベクター情報を数値化して出力可能で、今回はベクター情報を抽出し易い json 形式での出力結果を用いた

  3. ポリラインデータ変換ツールの作成
     上記の輪郭抽出ツールで出力された json 形式のファイルから後述の G850 用の描画ツールのフォーマットに対応した形式(アセンブラでの DB 命令形式で表現)への変換ツールを自作した
     json 用モジュールを利用することも考えたが、手っ取り早く正規表現でデータ抽出し、更に輪郭抽出ツールのポリラインデータ内には同一直線上に並ぶ複数のポイントが連続する部分が結構あったのでこれらを一つの直線にまとめる処理も実装した

  4. G850の描画処理の作成
     冒頭に書いたような高速ライン処理を組み込んだ描画コマンドデータを読みながら描画処理する簡易的なインタープリタを作成した
     実装したコマンドは「画面クリア」、「ポリライン描画」、「表示(LCDコントローラへのVRAM転送)」、「ウェイト」、「終了(Breakキー待ち)」の5つのみ

  5. 試験データ
     「ポケコン(G850)用拡張基板(その8)CP/MでBadApple!!」の記事での BadApple!! 動画から抽出した画像ファイルから上記のツールを用いて試験用の動画データを作成した

 今回の実験はポリラインによる動画再生の有効性の確認が主要な目的なのでメモリ増設していない標準のG850で動作するような試験プログラムを作成しました。具体的には 44 フレーム分(1秒ちょっと)のデータで使用メモリが6600Hの手前までになりました(データサイズは画像データの複雑さにも大きく依存します)。もちろん上記の BadApple!! 動画表示の記事のように CP/M 上で SD カードにデータファイルを置けば長時間の動画再生も可能になります。

 結果としては動画再生時にフレーム毎にある程度のウェイトを入れなければ再生速度が速すぎるくらいになったので、今回使った切り絵のような動画ではポリラインでの動画再生は有効であることが判りました。

 今回の実験ではフレーム間に一定時間のウェイトを入れましたが、ウェイトを入れないと画面の複雑さによる再生速度の違いが目立ったので、ポリライン変換処理において、ポリラインの合計の長さに応じたウェイト時間を計算する等の処理が有効だと思います(または動画再生処理側で再生時間をタイマー管理する)。

 下の写真はポリラインでの動画再生時に撮影したものです。画面の白黒情報が無くなり、輪郭だけになりますが動画としては十分に楽しめます。

ポリラインでの動画再生状況


★追記 2022/01/22
 Twitterに投稿した動画付きのメッセージを貼っておきます。



nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

Pic24MC68Kマイコン(その6)プリント基板で動作OK [68K]

 前回の記事から時間が経ってしまいましたが、元旦に製造依頼したプリント基板はとっくに届いているので部品を実装してみました。

 ブレッドボードで確認した回路なのでいつものようにすぐ動くと思っていましたが今回は PIC24 の OneBitLoader すらまともに動かず、原因調査&対処して無事動くようになりましたので調査内容や対処などについてメモとして記録しておきたいと思います。

 最初に Pickit で PIC24 に OneBitLoader を書き込んで起動してみました。
通常であれば"Welcome" メッセージを表示後に、押されたキーを表示するのですが、下図のように文字化けが酷い状態でした。

OneBitLoader 起動時の文字化けの様子


 文字化けの状態は安定せず、変化するようなのですが、'1'(0x31)の入力が'q'(0x71)に化けたりするのでシリアル通信のクロックが少しずれているようです。
 原因が USB/シリアルI/Fの PL2303 と PIC のどちらなのか切り分けるためにまずは PIC のシリアル受信と送信部の信号を確認しました。
 下図が PIC 側の受信信号例ですが、マーカー間が3bit分で 37.86(=12.62 x 3)Kbpsで通信速度は 38400bps なので許容範囲内です。信号自体もエッジの鈍り等は無く問題無いようです。

PIC 受信時のシリアル波形例(0x31受信時)


 下図が PIC の送信信号波形例でマーカー部の 1bit 分が 41.29KHz で設定値(38400bps)より結構高めの値です。これで PIC 側が問題の原因であることが判明しました。

PIC 送信時のシリアル波形例


 念のためにロジアナでも確認しましたが、受信側はokですが、送信側はバケバケでした。

PIC 送受信のロジアナ波形例


 問題個所が特定できたので PIC24 を交換する必要がありますが、ヒートガンでは近くの SDコネクタなどが影響を受けそうだったので、PIC のピンを切断してからピンを半田ごてで取り外しました。
 しかし、PIC を外す時に 43 番ピンのパターンが逝ってしまいましたorz
 このピンは D05(データバス)で接続先は基板の淵の方にあり距離があるので、直ぐ近くのスルホール部のレジストを剥がし、そこに半田付けするという難易度C? の技を試みてみましたw(クリックで拡大写真になります)

PIC43 番ピンのジャンパー接続


 ジャンパー部はアルコール洗浄後に保護のためにホットボンドで固めました。PIC を交換した結果、PIC で OneBitLoader が動き、自作の picleコンパイラ環境も問題無く導入できて、68K の動作試験プログラムである Hello 表示もできました(^^)/
 勿論、前回の記事で書いたS-record ローダーも動きました。

 更にうれしいことに、蟻さんから 5個組で買った MC68HC000P16 が最近届いたのですが、今回はいろんなものが混在していて、アルコールで拭くと P8(8MHzバージョン)に変身するものもありましたが、なんと 16MHz で動くものを1個見つけました(^^)/

 動作するようになった状態での写真等を貼っておきます。下の写真は 68K を実装前の TOP面です。

Pic24MC68K トップ面(MC68K実装前)


 次にボトム面です。

Pic24MC68K ボトム面


 MC68K 実装後は下の写真のようになります。アルコールで拭いて刻印が薄くなっているので刻印が見えるように斜めからストロボを当てています。

Pic24MC68K トップ面


 下の写真はUSBケーブルを接続して動作確認をしている様子で今までのブレッドボードよりはるかにコンパクトになっています。

動作試験中のPic24MC68K


 最後にreset直後から、68K の動作確認試験である "Hello" 表示のプログラムを実行した際のログを貼っておきます。68K は 16MHz で動作しています。あれ picle の起動メッセージが86のままになっていますねw

68K 試験のHello表示の実行状況
picle compiler CP/M-86 Ver0.01 2019/07/03 by skyriver :¥¥ +B000-B739 # HelloTest for Pic24MC68K +C000-CB3E #LibCpm for Pic24MC68K v0.01 2021/12/09 +D000-DEE9 #LibSpi SPI lib for Pic24MC68K V0.01 2021/12/07 :¥< 1849 :l 1:# HelloTest for Pic24MC68K 2:# Ver 0.01 2021/12/15 by skyriver 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var ProgStart,ProgWrk,WrkVal,_WrkVal,_PicDma,WrkTrk; 8:var EscFlg,EscY; 9: 10: 11:proc PicSrv() { 12: var i,fno,rval; 13: 14: while (1) { 15:# while (LATA[-1]&1) {} # wait reset 16: while ((LATA[-1]&3) = 3) {} # wait reset 17: if ( (LATA[-1]&2) = 0 ) { 18: PrnStr_( "¥nHALT!" ); 19: break; 20: } 21: PmpOn(); 22: PmpSetAdr(ProgWrk); 23: fno = MemRd(); # dummy 24: WrkVal[0] = MemRd(); 25: WrkVal[1] = MemRd(); 26: fno = _WrkVal[1]; # Func No 27: rval = 0; 28: 29: if (fno=1) { # CONST 30: if (InpChk_()) { 31: rval = $ff; 32: } 33: } 34: else if (fno=2) { # CONIN 35: rval = InpChar_(); 36: } 37: else if (fno=3) { # CONOUT 38: PrnChar_( _WrkVal[0] ); 39: } 40: else if (fno=0) { 41: break; 42: } else { 43: PrnStr_("¥nFunc err:"); 44: PrnHexB_( fno ); 45: break; 46: } 47: _WrkVal[3] = rval; 48: PmpSetAdr(ProgWrk+1); 49: MemWr(WrkVal[1]); 50: 51: PmpOff(); 52: BusRelease(); 53: } 54:} 55: 56: 57:proc m( dat ) { 58: MemWr( dat ); 59:} 60: 61: 62:proc main() { 63: init(); 64: initPmp(); 65: initSpi(); 66:# initSd(); 67: 68: ProgStart = $0600; # start addr(68K:0ffc00) 69: ProgWrk = $06f8; # work addr(68K:0ffdf0) 70: _PicDma = $0700; # Dma addr(68K:0ffe00) 512 71: WrkVal = Alloc( 2 ); 72: _WrkVal = WrkVal; 73: WrkTrk = Alloc( 2 ); 74: 75: LATA[-2]=LATA[-2]&$fffc; # on reset:a0 halt:a1 76: 77: PmpOn(); 78: PmpSetAdr(0); 79: MemWr($000f);# stack 80: MemWr($fc00); 81: MemWr($000f); # PC 82: MemWr($fc00); 83: 84: PmpSetAdr(ProgStart); 85: 86: 87: m($2c7c);m($000f);m($fc20);m($4241); 88: m($121e);m($6700);m($0008);m($6100); 89: m($0022);m($60f4);m($13fc);m($0000); 90: m($000f);m($fdf0);m($4e70);m($60fe); 91: m($0d0a);m($6865);m($6c6c);m($6f2c); 92: m($2077);m($6f72);m($6c64);m($0d0a); 93: m($00ff);m($0041);m($0300);m($33c1); 94: m($000f);m($fdf0);m($4e70);m($4e75); 95: 96: dump(0); 97: dump(ProgStart); 98: PmpOff(); 99: BusRelease(); 100: LATA[-2]=LATA[-2]|$3; # off reset:a0, halt:a1 101: 102: PicSrv(); 103: 104: PmpOn(); 105: LATA[-2]=LATA[-2]&$fffc; # on reset:a0 halt:a1 106:} :run 0000 : 000F FC00 000F FC00 28E3 8967 82B6 7F5C 0008 : 68B7 8A57 EA55 06B1 F27D 6BCF 80B5 DAD7 0010 : 3A78 3231 9CCF A855 BA59 B691 AA53 AF21 0018 : 873C 2E44 0FD9 A045 AE4F FC04 4E7D AA34 0020 : 0155 D367 AFEF 4D31 A8E2 EA74 6EB5 9BB4 0028 : 8A29 C311 2FF5 AAF7 CAE6 AB34 AC09 A5C4 0030 : AED4 6E5C BA56 EB0C 1F5D 04BB F377 6A5F 0038 : 1B5F 2463 785F E65C 0E11 BAFB BE9C 9ADE 0600 : 2C7C 000F FC20 4241 121E 6700 0008 6100 0608 : 0022 60F4 13FC 0000 000F FDF0 4E70 60FE 0610 : 0D0A 6865 6C6C 6F2C 2077 6F72 6C64 0D0A 0618 : 00FF 0041 0300 33C1 000F FDF0 4E70 4E75 0620 : 5303 51CA FFF4 2044 6100 0022 10C0 51CB 0628 : FFF8 60B2 6100 0034 B03C 0039 6E00 0008 0630 : 0400 0030 4E75 0400 0037 4E75 61E6 2200 0638 : E909 61E0 8041 4E75 6100 0010 B03C 000D hello, world :



[TOP] [ 前へ ] 連載記事 [ 次へ ]


nice!(0)  コメント(3) 
共通テーマ:趣味・カルチャー

ポケコン(G850)高速ライン描画 [ポケコン]

 「ポケコン(G850)用拡張基板(その8)CP/MでBadApple!!」の記事で SD カード上に置いたファイルを読込みながら動画再生できることを書きました。この時は動画が2値画像だったので 0x00 と 0xff のデータについてランレングス圧縮することで再生時のフレームレートを向上させることが出来ました。

 そこで直線で構成された線画画像やワイヤーフレームが回転するような画像であれば、ライン命令を高速に処理できれば動画再生が容易にできるのではないかとふと思いました(ライン命令はライン方向へのランレングス圧縮とも考えられる)

 ライン描画の高速化手法については例えば ここ に書かれているように両端からの同時描画ダブルステップ線分発生アルゴリズム等の手法があるようですがこれらの処理は Z80 のレジスタ上のみでの実現は難しいので今回は Z80 のレジスタ上で処理することによる高速ライン処理を実験してみました。

 冒頭に書いたように動画処理を念頭においているのでライン描画は VRAM 上で行い、1画面分の描画が完了した後に LCD コントローラに転送する方式にしています。

 下の写真がライン描画試験を行っている画面例です。LCD画面の上辺と下辺を逆方向に直線で結んでいます。X軸は4ドット間隔にして画面描画毎に1ドットずらしています。

ライン描画試験画面例


 3Dモデルを描画平面に写像してクリッピング結果をラインデータとして出力できる環境があればもっと気の利いたデモ画面ができるのですが・・・

 まぁ今回の高速ライン描画がいずれの日か役に立つこともあるかもしれませんねw


★追記 2022/01/18
 裏レジを使って上記の高速化手法である「両端からの同時描画」に対応してみました。
 元々裏レジを使っていたのでpush/popが多くなり、メインループのステート数が変更前:91、変更後:173で変更後のループ回数が 1/2 になるとすると、変更前:91 に対して変更後:86.5 になるので予想通りほとんど変わらないという結果でした。


★追記 2022/01/20
 Pset処理をLine描画ループ内に組込み、VRAMアドレス計算等を最小限にしてみました。
 予想通り、かなり高速化でき、LCDの反応が間に合わないくらいになりましたw
 動画付きのTwitterに投稿したメッセージを貼っておきます。


★追記 2022/01/22
 「ポケコン(G850)ポリラインで動画再生」の記事に高速ライン描画処理を使ったポリラインによる動画再生について記載しました。


nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

ポケコン(G850)LCDで階調表示 [ポケコン]

 「ポケコン(G850)用拡張基板(その8)CP/MでBadApple!!」で書いたように PC-G850V(以降、G850と記す)の CP/M 環境で SD カードに保存した画像データを使った動画再生ができ、 LCD の描画能力が結構高いことが判りました。
 動きが速い部分では二値化した動画の輪郭がグレーに見えたことから、今回は LCD を使った階調表示について書いてみます。

 ネットで検索すると G850 を使った4階調表示のゲームがあるようなので、今回は8階調表示に挑戦してみようと思います。
 原理は「階調表示用に8面の画面データを用意して、表示を高速で切替える」という単純なものです。
 8面の中の任意のピクセルについて明るいドットの総数が0~8個の9通りできるので0個の場合を除いたグレー部分の階調が8通りになります。

★追記 2022/02/22 {
 実際の画面データは8画面分無くても良く、8回の表示につき、それぞれ1,2,4回表示する3画面分のデータがあれば良く、複数回表示する画面についてはフリッカー対策のために等間隔(例えば4回表示の画面は2回に一回表示)に表示するようにすればいい。
}
 実際やってみると画面のちらつき(フリッカー)が発生してしまうので
  • 画面表示を如何に高速にするか
  • 画面表示間に適当なウェイト時間を入れフリッカーを最小限にする
等が肝になります。

 実験用の画像は、高品質なフリー素材を提供している pixaboy さんのサイトからダウンロードしたものを使用させて頂きました。

 G850 用の階調表示データを作成するために下記の処理を行っています。
  1. 画像ファイルのリサイズ
     ffmpeg を使ってポケコンの LCD のドットサイズである 144 x 48 の bmp ファイルにリサイズ

  2. 階調変換
     自作ツールにより、bmp ファイル内の各ピクセルを RGB データから8階調に分類
     8階調への分類手法は R+G+B の値で(最大値 - 最小値)を8つに等分割して分類するという簡易な方法を採用した

  3. 画面の連結
     最後に G850 の LCD イメージに並べた8画面分のデータを作成
     ※実際には上記の2と一緒に自作ツールで一括処理している

 上記の 1項 を行ったリサイズした画像が下図になります。

リサイズした画像サンプル


 下の写真は G850 で表示している様子です。タイミング調整したことでフリッカーもほとんど出なくなり結構綺麗に表示されるようになりました。
 下の写真では縮小した関係で少しモアレの縞模様が発生していますが、クリックして拡大すると無くなります。

G850での8階調表示例


 今回の実験で作成したヘキサファイルを下記からダウンロードできます。商用利用以外であれば自由に使用可能とします。
 使用方法は USER21FFコマンド(21FFより大きければ可)でメモリを確保後、ダウンロードし G100 のコマンドで実行できます。BREAK キーで終了します。
★追記 2022/01/15
 G850V以外の機種では表示タイミングの関係でフリッカーが発生する可能性があります。
その場合は 0159H からの2バイトデータを調整してみてください。

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー