2009/02/28

インターフェース誌9月号付録ColdFire基板(6):Nokia6100 LCD表示プログラム

ターゲット上のLCD初期化&表示プログラムです。
init()関数でターゲットおよびLCDを初期化します。
loadimg()関数がLCD表示を行う関数で、付録基板のGDBスタブ領域(0x20000)から一画面分のデータを決めうちで読み出して、LCDへ転送します。

実行例:
OK
init()
Init ColdFire Ports
Init LCD Driver (Philips PCF8833)

OK
loadimg()
Load Image to LCD from 0x20000 (takes long time...)
.....
OK

しかし、この最後のLCDへの転送が非常に遅くて、数十分のオーダの時間が掛かります。コード自体はもう少し最適化できると思いますし、CodeWarriorでユーザドライバというのも考えたのですが、そこまでの気力はありませんでした。
// LCD Display for Interface magazine's ColdFire Board
//
// * Silent-C (very slow...)
// * Nokia 6100 breakout board from Sparkfun electronics
//
// Taipapa

// Pin assignment
// 55 (AN0) <-> #CS (brown)
// 54 (AN1) <-> SCK (green)
// 53 (AN2) <-> DIO (blue)
// 52 (AN3) <-> #RESET (yellow)

char *ispbar = 0x40000000;
char *panpar = 0x4010006a;
char *ddran = 0x40100022;
char *portan = 0x4010000a;

// set signals
sigs(char cs, char sck, char dio, char reset)
{
char v;

v = ((reset<<3) | (dio << 2) | (sck << 1) | cs);
*portan = v;
}

// set signals, assume reset=1 and cs=0
sigs2(char sck, char dio)
{
*portan = (8 + (dio<<2) + (sck<<1));
}

// send 1 byte to LCD
// 0: command, 1: data
send(char cmd, char val)
{
int i;
char bit;

sigs(0, 0, 0, 1);

sigs2(0, cmd);
sigs2(1, cmd);

for(i=0; i<8; i++) {
bit = (val >> (7-i)) & 1;
sigs2(0, bit);
sigs2(1, bit);
}

sigs(1, 0, 0, 1);
}

// Initialization for Philips PCF8833
lcdinit()
{
PrStr("Init LCD Driver (Philips PCF8833)\r\n");

send(0, 0x11); // SLPOUT
send(0, 0x20); // INVON
send(0, 0x3A); // COLMOD
send(1, 0x3);
send(0, 0x36); // MADCTL
send(1, 0xc8);
send(0, 0x25); // SETCON
send(1, 0x30);
send(0, 0x29); // DISPON
}

// Initialization for ColdFire board
sysinit()
{
PrStr("Init ColdFire Ports\r\n");

// AN for digital out
*panpar = 0x0;

// AN for output
*ddran = 0xf;

// #RESET and #CS
sigs(1, 0, 0, 1);
}

init()
{
sysinit();
lcdinit();
}

loadimg()
{
int i;
char *p = 0x20000; // GDB stub area!!

PrStr("Load Image to LCD from 0x20000 (takes long time...)\r\n");

send(0, 0x2b); // PASET
send(1, 0);
send(1, 131);

send(0, 0x2a); // CASET
send(1, 0);
send(1, 131);

send(0, 0x2c); // RAMWR

for(i=0; i<26136; i++) {
if ((i & 0xff) == 0) {
PrStr(".");
}
send(1, *p);
p++;
}

send(0, 0); // NOP
}


以下、132x132のJPEGファイルをLCD転送用に変換する使い捨てスクリプトです。
これにJPEGファイルを食わせると、result.binというバイナリファイルが出来ます。それをCOLDFIRE.BINにリネームしてtftpでボードに転送すると、tftpサーバ側で自動的に0x20000からの領域に転送してくれます(転送後、PrHex(*0x20000)などで確認できます)。

スクリプト自体は、最近別の目的で作ったpythonスクリプトの流用で、ウィンドウを開くわけでもないのにGtkのPixmapを経由して変換を行うという、へなちょこスクリプトです。まあ使えれば良いのさ、ということにしておきます。

#!/usr/bin/env python

# JPEG to xfer format converter for Nokia 6100 LCD

# USAGE: nomia6001img.py jpg-file
# * Jpeg-file must be 132x132 jpeg file.
# * Output file is "result.bin"

import sys
import gobject
import math
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
import gtk.glade
except:
sys.exit(1)

buf = gtk.gdk.pixbuf_new_from_file(sys.argv[1])
x = buf.get_width()
y = buf.get_height()

# Size check
print "x =",x, "y =", y;
if (x!=132 or y!=132):
print "Size mismatch"
exit(1)

# Create pixmap
pix = gtk.gdk.Pixmap(None, x, y, 24)
vis = gtk.gdk.Visual(24, gtk.gdk.VISUAL_TRUE_COLOR);
cm = gtk.gdk.Colormap(vis, False)
pix.set_colormap(cm);

pix.draw_pixbuf(None, buf, 0, 0, 0, 0)

# Output result.bin
img = pix.get_image(0, 0, x, y)
f = open("result.bin", "wb")
for j in xrange(y):
for i in xrange(x/2):
p = img.get_pixel(i*2, j)
col = cm.query_color(p)
print "r1:", col.red, "g1:", col.green, "b1:", col.blue
r1 = col.red >> 12
g1 = col.green >> 12
b1 = col.blue >> 12

p = img.get_pixel(i*2+1, j)
col = cm.query_color(p)
print "r2:", col.red, "g2:", col.green, "b2:", col.blue
r2 = col.red >> 12
g2 = col.green >> 12
b2 = col.blue >> 12

# format is bgr
byte1 = b1 << 4 | g1
byte2 = r1 << 4 | b2
byte3 = g2 << 4 | r2

f.write(chr(byte1))
f.write(chr(byte2))
f.write(chr(byte3))

f.close

0 件のコメント: