2015年5月10日
128KバイトRAM搭載のPIC32MX370F512Hを用いた300×225ドット、256色同時表示が可能なビデオ出力システムの実験ではまだ少しだけシステムに余裕があったので、更に一歩進めて300×225ドットのグラフィック画面の上にテキスト画面を重ね合わせて表示するシステムを作りました。かつての8ビットや16ビットパソコンの多くは、テキスト画面とグラフィック画面を合わせ持っていました。それに似た環境を再現してみたいと思ったのがきっかけです。
応用範囲が広そうなので、扱いやすいようにビデオ出力関連とSDカードアクセス関連のそれぞれをライブラリ化して提供します。
(2015.5.19) ダウンロードファイルを更新しました
前回のグラフィックのみの300×225ドット、256色同時表示実験の回路と全く同じです。入力スイッチや音声出力は、今回も使用していませんので、この記事の実験を再現するだけであれば、特に接続は不要です。前回同様にブレッドボード上での実験を行いました。
回転スクロールシューティングゲーム「VELUDDA(ベルーダ)」もこの回路で動作します。
信号出力のタイミングについては前回同様のため、詳細は前回の実験を参照してください。
グラフィック画面は、300×225ドット、256色同時表示がほぼ限界のため、前回のものと変更なしとします。この上にテキスト画面を重ね合わせます。1キャラクターは8×8ドットで構成することが一般的なので、グラフィック画面に合わせると、横37.5文字、縦28.125文字まで表示可能です。これを扱いやすいところで横36文字、縦28文字としました。画面左上でグラフィックとテキストを合わせるので、画面右端の1文字半(12ドット)と最下行の1ドット分はグラフィック画面のみはみ出した表示となります。
ビデオメモリの構成は、グラフィック画面については前回と全く同様で1ドットにつき1バイトを割り当て256色同時表示としています。
また、テキスト画面については、1文字あたりキャラクターコードに1バイトとカラー1バイトの2バイトを図のように割り当てています。したがって、例えば配列TVRAMの要素0に値0x41を入れ、要素1044に7を入れると、画面左上にパレット番号7(デフォルトでは白)で「A」と表示されます。カラーパレットについては、グラフィックとテキストで共通となります。
テキストの行数は28行なのですが、プログラムの都合で29行分のメモリを保有しています。実際29行目に書き込むと1ドット分表示されてしまいますのでご注意ください。
フォントは、システム初期化時にフラッシュからRAMに読み込み、RAM上のものを画面表示します。そのため、アプリケーションから書き換えることが可能です。unsigned charの配列PCGの先頭からキャラクターコード順に、各文字8バイトで構成されています。上から順に1行あたり1バイト、左が上位ビット、右が下位ビットとなっています。
ビデオ出力システム本体と関連ライブラリのソースファイルを公開します。また、それらを簡単に扱えるようライブラリ化したファイル(拡張子.a)とインクルードファイルも提供します。SDカードへのアクセスはマイクロチップ社提供のソースファイルを使用して、こちらも本システムで簡単に扱えるようにライブラリ化したものを提供します。これらを扱うためのサンプルデモプログラムソースもまとめて下記リンクからダウンロード可能です。
利用する際は、MPLAB X環境でビルドしてください。CコンパイラはXC32 v1.32以下に対応しています。v1.33から仕様が変更となり、ライブラリとしてplib.hを使用すると警告が出るようになりました。
コンパイル時の最適化オプションはレベル1以上をお勧めします。(無償版でもレベル1は使用可能です。)
全ファイルのダウンロード |
SDカードに保存されたGIF形式の画像ファイルを読み込み、画面表示した後、画面にランダムな白い文字を上から順にひたすら表示します。最下行まで到達すると文字だけスクロールするので、グラフィックとテキストで画面が独立していることがわかります。
下記ファイルを全てプロジェクトに追加してビルドしてください。
<プロジェクトに追加するファイル>
TGvideo370fdemo1.c (mainプログラム)
TGvideo370fLib.X.a (システム本体)
TGvideo370f.h (システムを利用するためのヘッダー)
(以下はSDカード関連)
sdfsio370fLib.X.a
sdfsio370f.h
(以下はGIFファイル処理関連)
GifDecoder.c
GifDecoder.h
ImageDecoder.c
ImageDecoder.h
ImageDecoderConfig.h
サンプル画面。文字だけがスクロールします
プロジェクト構成
グラフィック関連のライブラリ利用方法を示したサンプルです。詳細は下記ライブラリの項を参照してください。テキスト関連は使用していません。
下記ファイルを全てプロジェクトに追加してビルドしてください。
<プロジェクトに追加するファイル>
TGvideo370fdemo2.c (mainプログラム)
TGvideo370fLib.X.a (システム本体)
TGvideo370f.h (システムを利用するためのヘッダー)
上記サンプルプログラム1動作時のメモリ使用量は、図のようにフラッシュ約68Kバイト、RAM約80Kバイトでした。RAMはかなりの割合を使用していますが、大半はグラフィックビデオメモリであり、残り48Kバイトもあれば十分いろいろなことができます。フラッシュは全体で512Kバイトもあるので、ほとんど気にすることはないでしょう。
テキスト画面で使用しているキャラクターコード表は図の通りです。昔のPCに合わせたコードとなっています。上述したように、初期化時にフラッシュからRAMにコピーしているので、アプリケーションから書き換えが可能です。
また、以下のライブラリでグラフィック画面にテキストを描画するための関数も用意していますが、この時のキャラクターコードとフォントも、この図と同じものです。こちらは動的な変更はできませんが、以下の名前の配列で初期データをプロジェクトに追加することでリンク時にライブラリより優先させることができます。
const unsigned char GFontData[256*8]
今回、ビデオ出力システム本体そのものと、関連する関数をまとめてライブラリ化しました。上記サンプルプログラムで説明したように、プロジェクトにTGvideo370fLib.X.aを追加し、TGvideo370f.hをインクルードするだけで利用することができます。
使い方はまず最初に、init_composite()関数を呼び出すことでビデオ出力が開始され、あとは以下のライブラリ関数を使って画面描画することができます。
また、SDカード(またはマイクロSDカード)を使用するためのライブラリ(sdfsio370fLib.X.aおよびsdfsio370f.h)も作成しました。こちらの詳細は、マイクロチップ社のヘルプファイルを添付しておりますので参照してください。
void init_composite(void)
システム初期化。画面消去して、テレビへの出力開始
void stop_composite(void)
画面出力停止
void start_composite(void)
画面出力再開。stop_composite()で停止したときの再開用
void clearscreen(void)
グラフィック画面消去(カラーパレット番号0で塗りつぶし)
void clearTVRAM(void)
テキスト画面消去(キャラクターコード0、カラーパレット番号0で埋める)
void set_palette(unsigned char n , unsigned char b , unsigned char r , unsigned char g)
カラーパレット設定
n:設定するカラーパレット番号(0〜15) ※以降カラーパレット番号は単純に「カラー」と略
r,g,b:赤、緑、青の強さ(各0〜255)
初期値は0〜7までは順に黒、青、赤、紫、緑、水色、黄、白。8は0と同じ。9〜15は1〜7の明るさ半分
以下の座標は文字描画も含め全てグラフィック座標系
void pset(int x , int y , unsigned int c)
座標(x,y)の位置にカラーcで点を描画
void line(int x1 , int y1 , int x2 , int y2 , unsigned int c)
座標(x1,y1)から(x2,y2)にカラーcで線分を描画
void hline(int x1 , int x2 , int y , unsigned int c)
座標(x1,y)から(x2,y)への水平ラインをカラーcで高速描画
void boxfill(int x1 , int y1 , int x2 , int y2 , unsigned int c)
座標(x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画
void circle(int x0 , int y0 , unsigned int r , unsigned int c)
座標(x0,y0)を中心に、半径r、カラーcの円を描画
void circlefill(int x0 , int y0 , unsigned int r , unsigned int c)
座標(x0,y0)を中心に、半径r、カラーcで塗られた円を描画
void putfont(int x , int y , unsigned int c , int bc , unsigned char n)
座標(x,y)にカラーcで8*8ドットのフォント表示
bc:背景色(文字部分以外の塗りつぶし色)を指定。負数の場合背景色での塗りつぶしなし
n:文字番号
void gprintstr(int x , int y , unsigned int c , int bc , unsigned char *s)
座標(x,y)にカラーcで文字列sを表示、bc:背景色(負数の場合背景色指定なし)
void gprintnum(int x , int y , unsigned char c , int bc , unsigned int n)
座標(x,y)にカラーcで数値nを10進数表示、bc:背景色(負数の場合背景色指定なし)
void gprintnum2(int x , int y , unsigned char c , int bc , unsigned int n , unsigned char e)
座標(x,y)にカラーcで数値nをe桁で右揃えして10進数表示、bc:背景色(負数の場合背景色指定なし)
void putbmpmn(int x , int y , char m , char n , const unsigned char bmp[ ])
横m*縦nドットのキャラクターを座標(x,y)に表示
サイズm*nの配列bmpに、単純にカラー番号を並べる
ただし、カラーが0の部分は透明色として扱う
void clrbmpmn(int x , int y , char m , char n)
縦m*横nドットのキャラクター消去(カラー0で塗りつぶし)
void cls(void)
テキスト画面を0でクリアし、カーソルを画面先頭に移動
void setcursor(unsigned char x , unsigned char y , unsigned char c)
カーソルをテキスト画面座標(x,y)に移動し、カラーcに設定
void setcursorcolor(unsigned char c)
カーソル位置そのままでカラーをcに設定
void printchar(unsigned char n)
カーソル位置にキャラクターコードnを1文字表示し、カーソルを1文字進める
void printstr(unsigned char *s)
カーソル位置に文字列sを表示
void printnum(unsigned int n)
カーソル位置に符号なし整数nを10進数表示
void printnum2(unsigned int n , unsigned char e)
カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める)
void vramscroll(void)
1行スクロール
void setPCG(unsigned char n , unsigned char *p)
テキスト画面用フォントの書き換え。n:キャラクターコード、pフォントパターン(8バイト)
PIC32MX370F512Hはフラッシュメモリ、RAMとも大容量で、動作速度も速いので、大変応用範囲の広いマイコンです。今回の実験はかつての8ビットや16ビット時代のパソコンで腕を鳴らした人にもお勧めできるものとなりました。これを使って以前作ったゲームなど再現してみられてはいかがでしょうか。今後、このシステムをさらに使いやすくしていきたいと考えています。