garlog改造への道 8

ていうか個人的なメモです。(H13.11.29)



  units.bmpを使う


 最近、loggerシリーズがv0.10からv0.20にバージョンアップしました。
 主なバージョンアップ内容は、割り込み処理の変更によるキー操作時の応答性の向上と、軌跡表示方法のリニューアル等です。
 特に軌跡表示については、GPSログ記録とは別に軌跡表示用のリングバッファを持つことにより、過去の軌跡が表示されるなど一層の機能アップがなされています。
 そこで今回はこのv0.20で強化された軌跡表示を勉強してみよう...と思ったのですが、その前に前回までやってきた各種情報の表示をもう少し煮詰めたいと思います。

 速度や高度など、いろんな情報を軌跡表示画面に表示させる時に困るのが、表示スペース不足です。
 2×2キャラクタ(16×16dot)で大きく表示する場合は尚更です。 特に単位の「m/s」とか「km/h」を表示させるのに場所を取られてしまうのがツライです。かといって単位は表示させたいし...
 そんなジレンマを解消するために?、gigoさんが作成したunits.bmpを使って単位を表示することにします。 units.bmpは、「m/s」と「km/h」を8×16dotに収めたフォントです。
 これです →
 これを使えば、3〜4文字ぶん必要な単位表示が、1文字分(8dot)で済みます。だから画面表示がスッキリするし、場合によっては更に情報を表示するスペースが確保できるわけです。
 では早速、ソースを改造してみることにします。(common.c)

 まずソースの頭に、units.bmpから変換されたunits.hをインクルードする行を追加します。


----------common.c----------------------------------------------------------------------------------

#include "alpha.h"
#include "numeric.h"
#include "separator.h"
#include "units.h"

----------------------------------------------------------------------------------------------------


 次にセパレータ文字テーブルの後ろ2文字に、m/sとkm/hの定義を追加します。
 単位に対応する文字は、「m/s」は'm'、「km/h」は'k'とします。
(他の記号を使うより分かりやすいし、大きな文字でmとかkといったアルファベットを表示させることはとりあえず無いと思ったので…)


----------common.c----------------------------------------------------------------------------------

static char cidx[] = " -ENSW./:\"'`";
    
static char cidx[] = " -ENSW./:\"'`mk";

----------------------------------------------------------------------------------------------------


 そして核心部分です。
 2x2キャラクタ(16x16dot)文字列を表示するvoid disp_x22_str()に、units.hを表示させる行の追加です。
 そのためにseparator(横8dot)を表示させる部分を真似て、if文を追加してunits(横8dot)を表示させます。


----------common.c----------------------------------------------------------------------------------

if ((d = sep2idx((char)d))>5) {
	d-=6;
	font_set_monodata(x, 1, &bmp_separator[d*16]);
	font_set_monodata(x+28, 1, &bmp_separator[d*16+8]);
	++x;
} else {
	font_set_monodata(x, 2, &bmp_alpha[d*32]);
	font_set_monodata(x+28, 2, &bmp_alpha[d*32+16]);
	x+=2;
}

    ↓↓↓

if ((d = sep2idx((char)d))>12) {
	d-=13;
	font_set_monodata(x, 1, &bmp_units[d*16]);
	font_set_monodata(x+28, 1, &bmp_units[d*16+8]);
	++x;
	} else {
		if ((d = sep2idx((char)d))>5) {
			d-=6;
			font_set_monodata(x, 1, &bmp_separator[d*16]);
			font_set_monodata(x+28, 1, &bmp_separator[d*16+8]);
			++x;
		} else {
			font_set_monodata(x, 2, &bmp_alpha[d*32]);
			font_set_monodata(x+28, 2, &bmp_alpha[d*32+16]);
			x+=2;
		}
	}

----------------------------------------------------------------------------------------------------
 オリジナル部分の変更は以上です。


 あとは今まで私が作ってきた改造部分(前回のgarlog改造への道7(H13.11.19)で表示させたもの)の中で、「m/s」や「km/h」を表示させる部分を変えるだけです。
 今まで数字はdisp_x22_str()(2x2キャラクタ)で描画し、単位のみtext_put_stringを使っていましたが、単位もdisp_x22_str()で表示させます。前述したように、「m/s」は'm'、「km/h」は'k'とすればOKです。


----------common.c----------------------------------------------------------------------------------

●風速表示(00.0m/s表示)
sprintf(msgbuff,"%2d.%dm/s",windSpd/10,windSpd%10);
text_put_string(4,16,msgbuff);
    
sprintf(msgbuff,"%2d.%dm",windSpd/10,windSpd%10);
disp_x22_str(4,15,msgbuff);


●速度表示(000km/h)
sprintf(msgbuff,"%3d",cnv.iSpd);
disp_x22_str(11,15,msgbuff);
text_put_string(17,15,"Km");
text_put_string(17,16,"/h");
    
sprintf(msgbuff,"%3dk",cnv.iSpd);
disp_x22_str(11,15,msgbuff);


●上昇/下降速度表示(0.0m/s)
sprintf(msgbuff,"%1d.%d",i/10,i%10);
disp_x22_str(21,15,msgbuff);
text_put_string(26,15,"m ");
text_put_string(26,16,"/s");
    
sprintf(msgbuff,"%1d.%dm",i/10,i%10);
disp_x22_str(21,15,msgbuff);

----------------------------------------------------------------------------------------------------


 common.cの改造は終わりました。
 あとはコンパイルして... と、その前に、makeファイルにunits.bmp関係の記述を追加しなければいけないような気がしました。
 makeファイルはコンパイルの流れを記述したバッチファイルみたいなもの(だと思う)ので、その中にunits.bmpをどうにかする文を追加します。早速dmcフォルダにあるmakelogger.dmcを読んでみると...良く分からないです。(^^;
 が、ここはいつもの作戦発動。似ている部分を見つけて、その真似をするのです。(^^;;

 それはどこかというと、同じようにbmpファイルをインクルード?してる部分です。そこにunits.bmp関係の記述を追加します。


----------makelogger.dmc---------------------------------------------------------------------------

59|garlog.obj: garlog.c wslogger.h userdef.h alpha.h numeric.h separator.h units.h
60|pnrlog.obj: pnrlog.c wslogger.h userdef.h alpha.h numeric.h separator.h units.h
61|stflog.obj: stflog.c wslogger.h userdef.h alpha.h numeric.h separator.h units.h
62|nmelog.obj: nmelog.c wslogger.h userdef.h alpha.h numeric.h separator.h units.h
63|ipslog.obj: ipslog.c wslogger.h userdef.h alpha.h numeric.h separator.h units.h


80|separator.h : separator.bmp
81|	bmpcnv -c separator.bmp
82|units.h : units.bmp
83|	bmpcnv -c units.bmp

---------------------------------------------------------------------------------------------------

これでOKのはずです。(ていうかダメだったらお手上げ(^^;; )

では、コンパイルしましょう。 dmcp_gar.bat(またはall.batやall_bmpsaver.bat)をダブルクリック!

できたgarlog.fxをTransMagicでSwanに転送します。 SummitをDEMOモードにしてgarlog起動です。

 あれま〜 なんか変です。(T_T)

 小数点のドットが2×2キャラクタになってるみたいだし、数字以外の大きな文字表示が変です。
 原因は、disp_x22_str()の中の今回改造した部分にありそうですが...




 追記 (11/30)

 ここでgigoさんからアドバイスをいただきました。

一番簡単なのは、separator.bmpにunits.bmpをペイントブラシなどで継ぎ足してcidx[]に
インデックスコードを加えることです。

>static char cidx[] = " -ENSW./:\"'`mk";

継ぎ足さない場合は、使用するbmpを切り替えているところ

>if ((d = sep2idx((char)d))>5) {
> d-=6; >略

に切り替えを追加しなくてはいけません。変更では駄目です。
今は、separator.bmpとunits.bmpがたまたま連続しているので一見、動いているように
見えるだけです。


 なるほどunits.bmpの内容をseparator.bmpにくっつけちゃえばいいんだ!
 言われてみれば最も簡単かつ分かりやすい方法です。
 初心者の私はなるべく簡単な方法でやろうとしてるんですが、その割に何故こういうシンプルな方法を思いつかなかったのか... 不覚でした。(^^;;

 では早速... といきたいところですが、ここはグッと我慢して、途中まで書いた今回の(units.bmpを個別に表示する)方法を、Cの勉強を兼ねて完成させてみようと思います。(でもしばらくやってダメだったら諦める予定。(^^;; )

 今回表示がうまくいかなかったソースリストを、gigoさんのアドバイスの後半を胸に、じっと眺めること30分。 ムム、見えてきました!
 disp_x22_str()にunits.bmp用のif文を追加しましたが、ここで d = sep2idx((char)d) という計算を行ってます。元々、dには文字のキャラクタコードが入っていて、sep2idx()によって その文字がcidx[]の何番目かが調べられ、dに入ります。つまりここでdの内容が変わってしまうのに、その下のif文で同じ計算をやってるからおかしくなるのです。
 そこで d = sep2idx((char)d) の計算を外に出し、if文は単にdの比較をするだけにします。
 つまり、
 ・まず当該の文字が数字ならnumeric.bmpを2×2で表示
 ・キャラクタコードからフォントフェースインデックスに変換
 ・13以上ならunits.bmpを1×2で表示
 ・6以上ならseparator.bmpを1×2で表示
 ・5以下ならalpha.bmpを2×2で表示
てな流れにすればいいと思います。

早速書いたソースが下です。disp_x22_str()の部分です。(太字が今回追加または変更した部分)


----------common.c----------------------------------------------------------------------------------

/* 2x2キャラクタ(16x16dot)文字列表示 */
void disp_x22_str(int x, int y, char *p)
{
	int d;

#ifdef WIN32
//	printf("%s\n",p);
#endif
	x += y*28+8;
//	while (*p++==' ')
//		x+=2;/* skip leading space */
	while ((d = *p++)!=0) {
		if (( '0' <= d) && (d <='9')) {
			d -= '0';
			font_set_monodata(x, 2, &bmp_numeric[d*32]);
			font_set_monodata(x+28, 2, &bmp_numeric[d*32+16]);
			x+=2;
		} else {
			d = sep2idx((char)d);
			if (d>12) {
				d-=13;
				font_set_monodata(x, 1, &bmp_units[d*16]);
				font_set_monodata(x+28, 1, &bmp_units[d*16+8]);
				++x;
			} else {
				if (d>5) {
					d-=6;
					font_set_monodata(x, 1, &bmp_separator[d*16]);
					font_set_monodata(x+28, 1, &bmp_separator[d*16+8]);
					++x;
				} else {
					font_set_monodata(x, 2, &bmp_alpha[d*32]);
					font_set_monodata(x+28, 2, &bmp_alpha[d*32+16]);
					x+=2;
				}
			}
		}
	}
}

---------------------------------------------------------------------------------------------------

 今度こそ平気だんべ。

 それ!!


 ヤッター! うまく出ました(^^)

 と、喜んだのも束の間。
 画面下部中央の20という数字、これは対地速度で単位は「km/h」のハズです。しかし表示は「m/s」。
 表示する部分でmとkを間違えてるんだろうと確認しましたが、

    sprintf(msgbuff,"%3dk",cnv.iSpd);
    disp_x22_str(12,15,msgbuff);

 と、ちゃんと「k」を入れてるし... 何故「km/h(実際はk/h)」表示が出ないのだろう?

 このプログラムは、まだまだ楽しめそうです。(←負け惜しみ^^; )




 追記 (12/1)


 苦節三日目、やっと原因がわかりました。

 まず、


static char cidx[] = " -ENSW./:\"'`mk";
 で、今回のunits.bmpに対応する mk までは13文字あるから、disp_x22_str()の中で

d = sep2idx((char)d);
if (d>12) {
	d-=13;
	font_set_monodata(x, 1, &bmp_units[d*16]);
	font_set_monodata(x+28, 1, &bmp_units[d*16+8]);
	++x;
 としてたんですが、よく見ればcidxの文字列にある「 \" 」というのは「 " (ダブルクォーテーション)」を表す拡張文字コードです。これを2文字分としてカウントしてたのが間違いでした。
 よって

d = sep2idx((char)d);
if (d>11) {
	d-=12;
	font_set_monodata(x, 1, &bmp_units[d*16]);
	font_set_monodata(x+28, 1, &bmp_units[d*16+8]);
	++x;
 とすればいいハズです。
 さっそくやってみると...

 今度こそ うまく出ました(^^)
 ちゃんと画面下の中央にある20という数字の単位が「 k/h (km/h)」になってます。

 要するに、昨日のソースは表示するbmpを切替える部分で1文字ずれて判別してたわけです。 だから文字「 k 」が来たとき、ひとつ手前の「 m 」に相当する「 m/s 」表示がされてしまったわけです。
 一方、文字「 m 」が来たときは、これはseparator.bmpだと判断されていた筈です。そして、あるはずのないseparator.bmpの7文字目を表示することになるのですが、separator.bmp と units.bmp のデータがメモリ上に連続して配置されていたため、一見ちゃんと「 m/s 」が表示されているように見えただけ... と推測しました。

 ...以上、わかってしまえば実に情けないバグでした。(^^;
 でもこれでスッキリしました。

 これで心おきなく別の方法(11/30の追記でgigoさんからアドバイスのあったシンプルな方法)に乗り換えられるってもんです。(^^;;


 続く...(かも)



目次に戻る