カテゴリ
リンク

当サイトは、玄箱PRO (KURO-BOX/Pro)を中心とした組み込み、Linuxと電子工作を扱っています。
会社案内

情報セキュリティおよび個人情報の取り扱いについて


コメントとトラックバックは、spamを予防するために、編集担当が公開の作業をするまで非公開になっています。コメントはそれぞれ投稿した人のものです。

■lcdproc とグラフィック液晶
  lcdproc は、基本的にはキャラクタ液晶(フォントを内蔵している)を前提としています。そのた め、フォントをもたないグラフィック液晶の場合には、ドライバでフォントを用意する必要がありま す。また日本語に対応していないので、表示する場合には改造が必要です。  ここでは、まず文字コードについて概略を解説します。
■文字コード(ASCIIコード)
  コンピュータで文字を扱う場合には、文字に数値を割り当てています。入力(キーボードと考えて も、エディタと考えてもよい)と出力(ディスプレイやプリンタ)までの間で、数値に対して割り当 てる文字が一貫しているから、正しく入力、処理、表示、印刷ができるのですが、このときの文字に 対する数値の割り当て方を文字コードと呼びます。英数字の場合には、ASCII コードが事実上標準に なっています(ASCII コードは慣用名だが、一般に使われている)。英数字(ウムラウトなどを除く) を表現するのに、0x20 から 0x7f が使われていて、1バイトで表現できます。

■JISコード
  日本語の場合の漢字に対する数値の割当は JIS で規格化されていて、事実上の標準になっていま す。文字の多さから、表現するのに2バイトが必要です。ただし、英数字の場合には、ASCII コード とプログラム上、ファイル上、通信プロトコル上の数値は1対1対応することがほとんどなのですが、 日本語の場合にはプログラムの書きやすさに合わせて、何通りかのコードがあります。

■漢字コード
  日本語の文字の扱い方としては、JIS, SJIS (shift JIS, シフトJIS), EUC-JP (Enhanced Unix Code), UTF-8 などが、よく使われています。JIS は主にメールなど、複数のシステム間でデータの やりとりをする場合に使われています。英数字と、漢字・かなの切り替えにシフトイン、シフトアウ トと呼ばれる特殊な文字列を使います。
ABC<シフトイン>日本語<シフトアウト>XYZ
 SJIS は、DOS, Windows や Mac で長く使われてきました。シフトイン、シフトアウトが必要ない コードです。制御文字 (0x00 から 0x1f), 英数字 (0x20 から 0x7f), 半角カナの範囲を避けるよう にして作られています。2バイト目に '\' (C言語で \n に使う `\' です)が含まれるため、それを考 慮したプログラムが必要になるという問題があります。  EUC は、主に UNIX 上のプログラムで使われてきたコードです。シフトイン、シフトアウトが必要 ない、JIS コードとの変換が容易、'\' が2バイト目に使われることがないと特長があります。半角カ ナを表現しようとすると3バイト必要になるというのがプログラム上問題になることがあります。
  UTF-8 は最近になって使われるようになりました。全世界の文字を一つのコードでコンパクトに表 現しようとしています。その代わりに、日本語と中国語、韓国語で字形の似た漢字を一つの文字で表 そうとしたり、漢字1文字が 3 バイトになったりという問題があります。

■文字列の長さとフォントの大きさ
  lcdproc のサーバ(LCDd)、クライアント(lcdproc, lcd-stuff など)では、文字列の表示に必要な 幅を strlen() で求めています。つまり、文字列のバイト数が表示幅の整数倍であると仮定していま す。これは、表示フォントが等幅の場合は正しいのですが、プロポーショナル・フォントでは成り立 ちません。また英数字以外の文字の場合に問題が出ることがあります。たとえば、JIS コードでは、 シフトイン、シフトアウトは表示されないのに、strlen()で数えられるという文字が含まれることに なります。
  もしも、英数字1に対して、漢字・かなが2の幅を持つことを仮定できるなら(英数字が半角で、漢 字かなが全角なら)、そして英数字が1バイトで表現され、漢字・かなが2バイトで表現されるなら、 strlen() で正しく文字列の表示幅を求めることができます。
  そのような漢字コードは、SJIS か EUC-JP です。SJIS は上記のように `\' の問題があるので、こ こでは EUC-JP を lcdproc のクライアント、サーバで利用することにします。

■キャラクタ液晶の英数字フォント
  lcdproc では、20文字×4行の液晶を仮定している書かれているクライアントも少なくないようで す。これはクライアント側で液晶の大きさにあわせて表示を整えるようになっていることも一因だと 思います。多くのキャラクタ液晶では、5×7ドットのフォント(英数字と半角カナ)の下に1ドットあ け(下線を引くため)、縦8ドット、横は文字間で少し隙間を空けています。これにならったのか、 秋月のグラフィック液晶でも 6x8 ドットのフォントが採用され、20×4行の表示ができるようになっ ています。

■sed1520ドライバのフォント
  秋月のグラフィック液晶は、 SUNLIKE の SG12232C を利用しています。これは、エプソンの SED1520という液晶コントローラのコマンド体系をベースにしていて、表示は横122ドット、縦32ドッ トになっています。この液晶コントローラを使ったデバイス用のドライバとして、sed1520 ドライバ が lcdproc にはあります。  SED1520 もグラフィック液晶なので、フォントは sed1520 ドライバがもっています (server/drivers/sed1520fm.c)。このフォントは 8×6ドットで、左端と下端を空行にして実質 5×7 ドットのフォントになっています。

■8×12ドットの日本語フォント
  sed1520 ドライバをベースとするならば、8×12 ドットのフォントがあればベストです。ただ横長 のフォントは見かけません。そこで 8×8 ドット(周囲に余白があり実質 7×7ドット)の美咲フォン トを利用し、左右に2ドットずつ余裕をもたせることにしました。

■sed1520ドライバの改造の概略
  sed1520 ドライバは、_clear(), _chr(), _string()関数は内部のバッファに書き込む構造になっ ているので、英数字については、それらの関数が利用できます。漢字・かなについては、美咲フォン トの読み込み (knj_fontload()関数)、漢字文字列の表示関数の用意(sed1520_string() 関数の改造 と、drawkchar2fb()関数の用意, 1バイトで漢字・かなはないので _chr() 関数はそのまま)をしてい ます。そして _flush() 関数を専用に用意しています。
  またバックライトへの対応、対応アイコンへの増加、_hbar(), _vbar()関数の保守などをしました 。詳細はソース・コードを眺めてみてください。

■漢字コードの取り扱い
  (半角カナをのぞく)EUC-JP の場合には、1バイト目も2バイト目も 0x80 より大きくなります。 このことを利用して、漢字・かなか英数字かの判別、不正な文字のチェック(バッファ・オーバフロ ー対策)をしています。EUC-JP から、JIS コードへの変換は、1バイト目を8ビット右シフトし、2バ イト目と論理和を取り、0x8080 を引くだけと簡単です。
MODULE_EXPORT void 
sed1520_string (Driver *drvthis, int x, int y, const char string[]) 
{ 
    PrivateData *p = drvthis-> private_data; 
    int i;   

    x--;			// Convert 1-based coords to 0-based 
    y--;   

    for (i = 0; string[i] != '¥0'; i++) { 
      if (string[i] < 0x80) { 
	drawchar2fb(p->framebuf, x + i, y, string[i]); 
      } else { 
	int knj = 0;   

	// If next byte is '¥0', we should stop here 
	if (string[i+1] == '¥0') 
	  break;   

	// EUC -> JIS 
	knj = ((string[i] << 8 ) | string[i+1]) - 0x8080; 
	drawkchar2fb(p-> framebuf, x + i, y, knj); 
	i ++; 
      } 
    } 
}

■BDF フォントの読み込み
  BDF フォントについては、美咲フォントに合わせて簡略化しています。一つの文字は、STARTCHAR から ENDCHAR までで、STARTCHAR の次が JIS コードです。BITMAP から先がフォントデータ(白と 黒の点)になります。美咲フォントでは、16進数で表現されているので、16進数を表した文字列を数 値に変換する関数(hex2i)を用意して、プログラム内の形式に変換しています。

 

STARTCHAR 2422 ENCODING 9250 SWIDTH 1097 0 DWIDTH 8 0 BBX 8 8 0 -2 BITMAP 20 7c 20 3c 6a b2 64 00 ENDCHAR

「あ」の例

 また、フォント・データは、各行が横の8ドット分を表していますが、プログラム内では液晶にあわ せて縦8ドットが1バイトに収まるような縦横の変換をしています(add2fontmap() 内で変換)。これに より、drawkchar2fb() の処理を簡単にしています。
                  MSB       LSB 
LSB □□■□□□□□     00100000        0x20 
    □■■■■■□□     01111100        0x7c 
    □□■□□□□□     00100000        0x20 
    □□■■■■□□     00111100        0x3c 
    □■■□■□■□     01101010        0x6a 
    ■□■■□□■□     10110010        0xb2 
    □■■□□■□□     01100100        0x64 
MSB □□□□□□□□     00000000        0x00 
    内部表記(16進)       2進数表記   misaki.bdf での16進表記 
    20  7f  16  30 
      52  26  4a  00
 それから、JIS コードの数値は連続していないので、そのままメモリを確保すると無駄が生じるの で、jis2id() 関数を用意して内部で使用するメモリを減らしています。

■書き換えを減らす
  akiglcd_flush関数 (sed1520_flush() 関数から呼ばれる)では、通信量を減らすために、各行を半 分にした画面を8分割にし、それぞれの領域で書き換えがない場合には、そこをスキップするように しています。また、0x1b (ESC) を液晶モジュールが受け取るとコマンドと解釈して動作がおかしく なるので、0x3b に置き換えています(本来は PIC のファームウェアを書き換え、ESC が正しく表示さ れるようにするべきです)。  また、ここでは write() 関数を直接使ってグラフィック・データを送っていますが、フォントを読 み込むような時間がかからないので問題はありません。
static void 
akiglcd_flush (Driver *drvthis) 
{ 
  PrivateData *p = drvthis->private_data; 
  const static char *aglcd_col[] = {aglcd_home, 
				    "x1bN0610r", 
				    aglcd_col2, 
				    "x1bN0611r", 
				    aglcd_col3, 
				    "x1bN0612r", 
				    aglcd_col4, 
  				    "x1bN0613r"}; 
  unsigned char *o, *n; 
  int i, j, skip = 1;   

  debug(RPT_DEBUG, "%s: FLUSHn",drvthis->name);   

  o = p->framebuf0; 
  n = p->framebuf;   

  for (i=0; i
 
    if (*(n+i) == 'x1b') 
      *(n+i) = 'x3b'; // XXX 
  }   

  for (i=0; i<4; i ++) { 
    for (j=0; j<2; j ++) { 
      if (bcmp(n, o, PIXELWIDTH/2) != 0) { 
	if (skip != 0) { 
	  akiglcd_write(p->fd, aglcd_col[i*2 + j], 7); 
	  akiglcd_checkret(p->fd, '@'); 
	} 
	write(p->fd, n, PIXELWIDTH/2); 
	usleep(1*1000); 
	bcopy(n, o, PIXELWIDTH/2); 
	skip = 0; 
      } else { 
	skip = 1; 
      }   

      o += (PIXELWIDTH/2); 
      n += (PIXELWIDTH/2); 
    } 
  } 
}
<光永 法明>

 カテゴリ 

 

トラックバック(0)

このブログ記事を参照しているブログ一覧: lcdproc のドライバの書き方 (後編)

このブログ記事に対するトラックバックURL: http://www.eleki-jack.com/mt/mt-tb.cgi/1222

コメントする

おすすめ書籍
Powered by
Movable Type 4.1