|
楼主 |
发表于 2004-10-12 22:26:17
|
显示全部楼层
EP7312的LCD帧缓冲中,每个象素是4位,可以表示16个灰度值。相邻的3个像素的灰度值组成屏幕上的一个点。
这样就形成屏幕上的一个点的颜色值由12位表示,低4位相当于红色分量,中间4位相当于绿色分量,高4位相当于蓝色分量。
不知道我理解的对不对?
我在SkyEye-0.8.0的sim/arm/skyeye_lcd.c中修改expose_event函数:
expose_event (GtkWidget *widget, GdkEventExpose *event)
{
int loopnum;
int i;
guchar fbdata_low;
guchar fbdata_medium;
guchar fbdata_high;
loopnum = (lcd_width * lcd_height * lcd_depth) / (8 * 3);
fbSkyeyeADDR = rgbbuf;
switch (lcd_depth)
{
case 8:
gdk_draw_indexed_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
0 , 0,lcd_width ,lcd_height,
GDK_RGB_DITHER_NORMAL, rgbbuf,lcd_width,colormap);
break;
case 12:
for (i = 0; i < loopnum; i++)
{
fbdata_low = *(fbSkyeyeADDR++);
fbdata_medium = *(fbSkyeyeADDR++);
fbdata_high = *(fbSkyeyeADDR++);
*(rgbbuf_24 + i * 6 + 0) = ((fbdata_low & 0x0f) << 4);
*(rgbbuf_24 + i * 6 + 1) = (fbdata_low & 0xf0);
*(rgbbuf_24 + i * 6 + 2) = ((fbdata_medium & 0x0f) << 4);
*(rgbbuf_24 + i * 6 + 3) = (fbdata_medium & 0xf0);
*(rgbbuf_24 + i * 6 + 4) = ((fbdata_high & 0x0f) << 4);
*(rgbbuf_24 + i * 6 + 5) = (fbdata_high & 0xf0);
}
gdk_draw_rgb_image(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
0, 0, lcd_width, lcd_height,
GDK_RGB_DITHER_NORMAL, rgbbuf_24, lcd_width * 3);
break;
default:
break;
}
return TRUE;
}
将LCD帧缓冲区(rgbbuf)的每一个12位的颜色值转换成为一个24位的颜色值放到新申请的颜色缓冲区(rgbbuf_24)中,在调用gdk_draw_rgb_image将rgbbuf_24这个新的缓冲区影射到模拟的LCD窗口中。
目前的实现方法比较直观:
原有的缓冲区中以三个字节为一组,它存放了两个点的颜色值,第一个点的颜色值为(R1, G1, B1),第一个点的颜色值为(R2, G2, B2)。每一个颜色分量都为4位。将每一个点的各个分量都右移4位,扩展成8位,对应生成的两个点的新颜色值共占6个字节。
我现在的问题很奇怪:
在图像显示过程中,有画屏现象,但最终的显示结果是基本正确的(除了下面说的那个问题);
LCD屏幕最左上角的3像素点不能读写,总是黑色;
我不知道lcd_write这个函数是不是还要进行修改,因为这个函数的实现还不是太明白。
我觉得在读写LCD帧缓冲时,其实还是以4位为单位来做的,所以目前的修改就是把它当成4位做的:p
void lcd_write(ARMul_State *state, ARMword addr, ARMword data)
{
ARMword offset;
int pixnum, bit;
guchar pix;
guchar *pos;
ARMword swapdata=0;
int k;
int step;
if (lcd_depth == 12)
{
step = lcd_depth / 3;
}
else
{
step = lcd_depth;
}
if (skyeye_config.no_lcd)
return;
offset = (addr & ~3) - lcd_base;
pixnum = offset * 8 / step;
if (pixnum<lcd_width*lcd_height) {
pos=rgbbuf+pixnum;
switch(lcd_depth){
case 1:
break;
case 2:
break;
case 4:
case 12:
for(k=0;k<32;k+=4){
if((k/4)&0x01){
swapdata=swapdata | (((data>>(k-4))&0x0f)<<(k));
}else{
swapdata=swapdata | (((data>>(k+4))&0x0f)<<(k));
}
}
data=swapdata;
break;
default:
break;
}
for(bit = 0; bit < 32; bit += step/*lcd_depth*/){
pix = (data >> bit) % (1 << step/*lcd_depth*/) ;
*pos++ = pix;
lcd_changed = TRUE;
}
}
}
还请halfyear指点一下 |
|