北京理工大学 20981 陈罡
这个说起来,大家应嘎不会陌生,做过传统linux平台的底层开发的大侠对我下面说的东西
一定早就非常了解了。hoho,班门弄斧了。
(1)vga操作:framebuffer
一般gui编程和操作,大家都会选择合适的gui库如xlib, gtk, qt或者tcl, tk, ncurses
a1200是一个不全开放的linux系统,目前采用的内核是2.4.33,它的gui系统其实是一个
经过改造的qte库的封装,内部名称为ezx,目前由于qt的商业开发版权问题,moto一直
不敢公开他们的gui开发库。网上流传的很多也只是ezx在某个平台上面,由一些黑客
破解的。所谓的破解,只是把这些libezx*.so反编译,找到这些库对应的函数名和偏移,
然后重新编写这些函数的头文件,然后应用程序的开发者,利用这些还原了的头文件
和手机上本身的lib,就可以利用arm-linux工具链,让应用程序在a1200上跑起来了。
在这里,我不愿意过多评论ezx库,毕竟它是不开放的,代码即使在e680上能跑了,
在a1200上也未必能运行。我这里讨论的是更加“通用”的framebuffer操作。
a1200的framebuffer设备文件为:/dev/fb0
不需要什么配置,直接调用open打开即可,剩下的就是像素格式操作了。
我已经在《moto a1200开发随笔(1)--硬件基本信息》文章中提到像素格式的问题,
在此,重新引用一遍,加深一下印象:
vga : 240x320的触摸屏,色深为packed 18bpp格式
注意,packed 18bpp是对应着16bpp像素格式定义(rgb565):
rrrrrggg gggbbbbb
这里的packed 18bpp的像素格式定义为(rgb666):
000000rr rrrrgggg ggbbbbbb
还有一种与24bpp像素格式兼容的aligned 18bpp格式,像素定义为(rgb666):
00rrrrrr 00gggggg 00bbbbbb
也有如下定义的格式:
rrrrrr00 gggggg00 bbbbbb00
天知道为什么moto要采用18bpp,或许这和intel的pxa270片子对液晶屏幕的驱动
电路有关,反正这样18bpp也是用了3个字节保存一个像素,那么干嘛不采用
aligned 18bpp呢?又可以和24bpp像素格式兼容,速度又快。这一点,很多人
都不理解,我也是做了两个多小时的试验,才试出来。让人发疯的moto。
贴一个简单的put_pixel函数例子:
int ezfb_put_pixel(struct ezfb* fb, u_int x, u_int y, u_int c)
{
EZFB_NIT_PICKING_FUNCTION_CALL_0
register int idx = 0 ;
if(fb->exists && (x < fb->Var.xres_virtual) && (y < fb->Var.yres))
{
switch(fb->Var.bits_per_pixel) {
case 1: break;
case 2: break;
case 4:
{
idx = (y * fb->Fix.line_length + x) / 2;
fb->screen_uchars[idx] = (x & 0x01) // odd
? ((fb->screen_uchars[idx] & 0x0F) | ((c & 0x0F) << 4))
: ((fb->screen_uchars[idx] & 0xF0) | (c & 0x0F));
break;
}
case 8:
{
idx = y * fb->Fix.line_length + x ;
fb->screen_uchars[idx] = c;
break;
}
case 15:
case 16:
{
idx = y * fb->Fix.line_length + x ;
fb->screen_ushorts[idx] = c;
break;
}
case 18:
case 24:
{
// rgb format is rrrrrrrr gggggggg bbbbbb
idx = y * fb->Fix.line_length + x * 3 ;
fb->screen_uchars[idx++] = (c & 0x00000ff) ;
fb->screen_uchars[idx++] = (c & 0x000ff00) >> 0x08 ;
fb->screen_uchars[idx++] = (c & 0x0ff0000) >> 0x10 ;
break ;
}
case 32:
{
idx = y * fb->Fix.line_length + x ;
fb->screen_uints[idx] = c;
break;
}
default: ;
}
ret = 1;
}
EZFB_NIT_PICKING_FUNCTION_RETURN(ret)
}
这个是把一个像素的颜色赋值到frame buffer中的小例子。
直接写屏的代码:
void ezfb_put_screen(struct ezfb* fb, u_char * mem_buf, int buf_mode)
{
int w = fb->Var.xres ;
int h = fb->Var.yres ;
register union {
u_char a[4] ;
u_int clr ;
} v ;
int i, j ;
switch(fb->Var.bits_per_pixel) {
case 8:
case 16:
{
}
case 18:
{
switch(buf_mode) {
case MODE_BPP8:
case MODE_BPP16:
{
// convert 16bpp mem buffer to packed 18bpp
u_short * src = (u_short *)(mem_buf) ;
volatile u_char * dst = fb->screen_uchars ;
for(i = 0 ; i < h ; i++) {
for(j = 0 ; j < w ; j++) {
v.clr = *src++ ;
// convert rgb565 to rgb666 packed
v.clr = ((v.clr & 0x0001f) << 1) |
((v.clr & 0x007e0) << 1) |
((v.clr & 0x0f800) << 2) ;
*dst++ = v.a[0] ;
*dst++ = v.a[1] ;
*dst++ = v.a[2] ;
}
}
break ;
}
case MODE_BPP24:
case MODE_BPP32:
default:
break ;
}
break ;
}
case 24:
case 32:
default:
break ;
}
}
这些都是真机测试通过的喔!!
如上图所示,中文显示是用的12x12,16x16的点阵字库搞得,效果还可以吧。
图片是移植了cximage库完成的,上图是a1200真机抓屏。
(2)声音:
a1200的声音文件映射为:/dev/dsp和/dev/dsp16
其中/dev/dsp支持16位pcm,44.1khz的stereo(双声道)音频播放
/dev/dsp16支持16位pcm,8khz的mono(单声道)音频播放
具体操作的时候,根据你选择的解码器输出可以自由选择。
呵呵,偶移植的是libmad,很好用支持mp3播放。
关于音量控制,a1200采用的oss的声音驱动模型,因此常规的alsa的
音量调整不好用。我测试过,cmixer之类的open source软件,放到
a1200上面以后,根本不能够调节音量大小,这个问题曾经困扰了我挺
长时间的,不过现在好了,找到了音量调节的方法:
int fd, v = 30; // v代表音量,取值为0..100,0代表静音,100是那种撕裂的大音量,让人难受
fd = open("/dev/mixer", O_RDONLY);
ioctl(fd, SOUND_MIXER_WRITE_VOLUME, &v);
ioctl(fd, SOUND_MIXER_READ_OGAIN, &v);
printf("VOLUME = %d\n", v);
简单的一段代码就可以解决。
该图片也为未完成的xmms的移植的真机抓屏,可以播放mp3文件。
其实真机抓屏特简单,直接运行软件,然后在telnet里面执行cat /dev/fb0 > xxx.dat
然后把xxx.dat转换成bmp格式,就一切ok。
(3)震动功能的映射文件为:/dev/vibrator
(4)接电话、sms映射文件: /dev/mux0
阅读(4576) | 评论(3) | 转发(0) |