Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1532623
  • 博文数量: 114
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 1357
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-19 18:13
文章分类
文章存档

2010年(8)

2009年(9)

2008年(27)

2007年(62)

2006年(8)

我的朋友

分类: LINUX

2007-07-29 23:30:40

 
北京理工大学 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) |
给主人留下些什么吧!~~

chinaunix网友2009-01-06 12:23:13

这段到底怎么应用呢 程序的参数定义是什么?