曙海教育集团论坛VxWorks专区VxWorks 应用开发 → 实时操作系统VxWorks下电子海图系统打印功能的实现


  共有4266人关注过本帖树形打印

主题:实时操作系统VxWorks下电子海图系统打印功能的实现

美女呀,离线,留言给我吧!
wangxinxin
  1楼 个性首页 | 博客 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:青蜂侠 帖子:1393 积分:14038 威望:0 精华:0 注册:2010-11-12 11:08:23
实时操作系统VxWorks下电子海图系统打印功能的实现  发帖心情 Post By:2010-12-1 11:34:46

1 前 言

  电子海图系统是一种把需要向航海人员显示和解释的各种各样信息融成一体的实时导航系统,是地理信息系统在舰船组合导航系统中的重要应用,被认为是继雷达/ARPA之后在舰船导航方面又一项伟大的技术革命。与简单地用颜色显示的纸海图相比,电子海图系统包括更多的使用简单、操作容易的地理和文字信息。作为一种自动判定仪器,它能够连续测定船舶相对于陆地、图示物标、导航标志和不可见碍航物的位置,对海上航行、安全和商业都有重要意义。

  VxWorks是一种嵌入式的实时操作系统。将应用较为广泛的电子海图系统移植到VxWorks操作系统下的主要原因有两个:一是VxWorks系统的实时性,能够很好的满足导航系统实时性的要求;二是基于信息安全方面的考虑,海图系统要求一种保密性好、没有漏洞的操作系统,使用VxWorks操作系统,程序开发者可以进行最底层的程序开发,能够完全控制系统的资源,确保海图信息的安全。

2 电子海图系统打印功能的总体设计思路

  在VxWorks操作系统中,实现电子海图信息打印功能设计的总体思路是:首先将打印内容,包括图像和报表,转换成恰当格式的图像文件,如PostScript文件,而后对于没有内置PostScript语言解释器的打印机,需要将PostScript语言解释成打印机可以识别的语言,最后把图像文件输送到打印机。

  本文介绍基于内置有PostScript语言解释器的HP LaserJet 1200打印机,在VxWorks操作系统下,完成电子海图信息打印功能的实现过程。

3 打印驱动

  打印机驱动程序中的各个函数的实现:

  (1)基本的I/O函数的实现
  根据打印机并口的特点,驱动程序中要实现的基本的I/O函数应该是lptOpen(…)、lptRead(…)、lptWrite(…)和lptIoctl(…)。这4个基本函数的声明分别是:

  LOCAL int lptOpen(LPT_DEV*pDev,char*name,int mode);  LOCAL int lptRead(LPT_DEV*pDev,char*pBuf,int size);
  LOCAL int lptWrite(LPT_DEV*pDev,char*pBuf,int size);
  LOCAL STATUS lptIoctl(LPT_DEV*pDev,int function,int arg);  其中LPT_DEV结构的定义为:
  typedef struct lptDev
  {
  DEV_HDR devHdr;
  BOOL created;/*TRUE if this device has been created*/
  BOOL autofeed;/* TRUE if enable autofeed */
  BOOL inservice;/* TRUE if interrupt in service */
  USHORT data; /* data register */
  USHORT stat; /* status register */
  USHORT ctrl; /* control register */
  int intCnt;/* interrupt count */
  int retryCnt; /* retry count */
  int busyWait; /* loop count for BUSY wait */
  int strobeWait;/* loop count for STROBE wait */
  int timeout; /* timeout second for syncSem */
  int intLevel; /* interrupt level */
  SEMAPHORE muteSem;/* mutex semaphore */
  SEMAPHORE syncSem;/* sync semaphore */
} LPT_DEV

  DEV_HDR是所有设备的头结构,是由VxWorks系统定义的,定义为:

  typedef struct/* DEV_HDR device header for all device structures*/
{
  DL_NODE node; /* device linked list node */
  short drvNum; /* driver number for this device */
  char * name; /* device name */
} DEV_HDR

  (2)设备的硬件初始化函数xxDrv(…)的实现

  该函数的声明为:
  STATUS lptDrv(int channels, LPT_RESOURCE *pResource)

  其中,参数channels 为打印并口的通道号;参数pResource是指向结构LPT_RESOURCE的指针,结构LPT_RESOURCE的定义为:

  typedef struct lptResource /* LPT_RESOURCE */
{
  int ioBase;/* IO base address */
  int intVector;/* interrupt vector */
  int intLevel; /* interrupt level */
  BOOL autofeed;/* TRUE if enable autofeed */
  int busyWait; /* loop count for BUSY wait */
  int strobeWait;/* loop count for STROBE wait */
  int retryCnt; /* retry count */
  int timeout; /* timeout second for syncSem */
}LPT_RESOURCE;

  该函数lptDrv(int channels, LPT_RESOURCE *pResource)完成了打印机并口的初始化,其中调用函数intConnect(…)和iosDrvInstall(…)的具体形式为:

  (void)intConnect((VOIDFUNCPTR*)INUM_TO_IVEC(pResource->intVector),
  (VOIDFUNCPTR)lptIntr, (int)pDev);
  lptDrvNum = iosDrvInstall (lptOpen, (FUNCPTR) NULL, lptOpen,
  (FUNCPTR) NULL, lptRead, lptWrite, lptIoctl);

  (3)设备的创建函数xxDevCreate(…)的实现

  该函数的声明为:
  STATUS lptDevCreate (char *name, int channel)

  该函数将设备的创建标志置为TRUE,然后调用函数iosDevAdd (&lptDev[annel],devHdr.name, lptDrvNum) 将创建的设备加入I/O系统中。

  对于打印驱动程序,重点在于函数lptWrite(…)的编写,这个函数的实现可采用两种方式。一种是中断方式,即将控制寄存器中的允许中断位置为1,这样,打印机每打印输出一个字符后,立即向主机发出中断请求信号,要求发送下一个字符;主机方面只要在中断服务程序中实现数据传输即可,而不必循环查询打印机的“忙”信号。另一种是查询方式,用这种方式时,主机不停地测试打印机的“忙”信号,当检测到打印机不忙时,便向其发送打印数据,若打印忙,则主机必须等待,直到打印机不忙。

  根据编写打印机驱动程序的两种方式,选用查询方式,其流程如图1。

图片点击可在新窗口打开查看

4 PostScript文件的生成

  在VxWorks操作系统的开发环境Tornado下,软件包ZINC中的ZafPrinter类及ZafDisplay类提供的函数可完成PostScript文件的生成。ZafPrinter类继承ZafDisplay 类而来,因此,在ZafPrinter 中除了继承来的图形显示函数之外,还定义了与打印机接口相关的函数,如BeginJob(),EndJob(),BeginPage(),EndPage()等。

  在用ZINC自带的程序生成PostScript文件时,需注意以下几点:

  (1)将自定义的颜色值加入颜色表中,在i_print.cpp文件(在目录…\Tornado\target\src\zinc\generic下)中,原来的颜色表定义为:

  static unsigned long psColorTable[16]=
  {
  0x00000000L, // 0-ZAF_CLR_BLACK
  0x00000080L, // 1-ZAF_CLR_BLUE
  0x00008000L, // 2-ZAF_CLR_GREEN
  0x00008080L, // 3-ZAF_CLR_CYAN
  0x00800000L, // 4-ZAF_CLR_RED
  0x00800080L, // 5-ZAF_CLR_MAGENTA
  0x00808000L, // 6-ZAF_CLR_BROWN
  0x00C0C0C0L, // 7-ZAF_CLR_LIGHTGRAY
  0x00808080L, // 8-ZAF_CLR_DARKGRAY
  0x000000FFL, // 9-ZAF_CLR_LIGHTBLUE
  0x0000FF00L, // 10-ZAF_CLR_LIGHTGREEN
  0x0000FFFFL, // 11-ZAF_CLR_LIGHTCYAN
  0x00FF0000L, // 12-ZAF_CLR_LIGHTRED
  0x00FF00FFL, // 13-ZAF_CLR_LIGHTMAGENTA
  0x00FFFF00L, // 14-ZAF_CLR_YELLOW
  0x00FFFFFFL, // 15-ZAF_CLR_WHITE
  };

  保留原有的16种颜色,再增加48种海图中的颜色:

  0x00000000, 0x00000080, 0x0000b400, 0x0080ffff,
  0x00d20000, 0x00ff00ff, 0x00dc8000, 0x00c0c0c0,
  0x00ffc7ab, 0x000000ff, 0x0000ff00, 0x00c8ffff,
  0x00ff0000, 0x00ff96ff, 0x00ffffc0, 0x00ffffff,
  0x00ff02fd, 0x00ff02fd, 0x00ff02fd, 0x00ff02fd,
  0x00ff02fd, 0x00ff02fd, 0x00ff02fd, 0x00ff02fd,
  0x00ff02fd, 0x00ff02fd, 0x00ff02fd, 0x00ff02fd,
  0x00ff02fd, 0x00ff02fd, 0x00ff02fd, 0x00ff02fd,
  0x00000000, 0x000000ff, 0x0033aa00, 0x0060c0c0,
  0x00b03030, 0x00c040c0, 0x00804040, 0x00a0a0a0,
  0x00404040, 0x008080ff, 0x0080ff80, 0x0016edfe,
  0x00e02020, 0x00e010e0, 0x00ffff80, 0x00ffffff,

  这样颜色表中共有64种可用颜色。

  同时将
  for(index = 0; index < 16; index++)
    colorTable[index]= psColorTable[index];

  改为:
  for(index = 0; index < 64; index++)
  colorTable[index]= psColorTable[index];

  (2)为使生成的PostScript文件尽可能的小,对原来海图的画图程序做了一点改动。在原程序中,多边形的绘制是通过画两点线完成的,这样,生成PostScript文件比较大,可将其改为直接调用画多边形的函数Polygon()。经过这样的改动,生成的PostScript文件减小了很多,原来的一页图生成的PostScript文件为3.65M,改动后不足1M。

5 PostScript 文件在VxWorks操作系统下的打印输出

  要使用打印驱动程序,首先要调用函数lptDevCreate(char*name,intchannel)为LPT端口创建设备,其中端口号由参数channel指定,创建的设备的名称为name。只能为一个端口号创建一个设备。
  创建设备成功之后,主机就可以向打印机发送PostScript文件了,其程序流程如图2。

图片点击可在新窗口打开查看

6 汉字打印输出的实现

  在VxWorks操作系统下,实现电子海图中汉字的显示和打印输出功能的基本思路是:利用Windows操作系统中的TrueType字库,根据需要显示汉字的Unicode编码,在TrueType字库中找到该汉字的相应信息,按照TrueType字库中存储的信息,将汉字显示或打印输出。

  TrueType字库由很多表组成,它是用一些闭合的轮廓线来描述每个字符的。若能够访问TrueType字库获得相应汉字的描述信息,就能将汉字画出来。对于TrueType字库的访问,网上有开放的资源可以实现,这就是FreeType2,它为应用程序访问字库文件提供了统一的接口,支持的格式包括TrueType, OpenType, Type1, CID, CFF, Windows FON/FNT, X11 PCF等。要使用FreeType, 就要在相应的操作系统下对源代码进行编译,生成一个库文件,然后在应用程序中调用相应的API库函数。

  通过FreeType提供的库函数,应用程序可以访问TrueType字库,根据所得到的TrueType汉字信息,就能实现TrueType字体的显示或打印输出。但是TrueType字库的访问是通过Unicode编码进行的,也就是说,只有获得了字符的Unicode编码,才能在TrueType字库中得到该字符的描述信息。在电子海图程序中,字符的Unicode编码的获得是通过查表实现的。所谓的查表,是指将国际汉字字符集中所有字符的Unicode编码,存在一个数组unsigned long gb2312_uni_data[87][94],根据字符的区位码就可以得到相应的Unicode编码。例如区号为qh,位号为wh的字符的Unicode编码就是数组元素gb2312_uni_data[qh-1][wh-1]的值。

  保存所有字符的Unicode编码的数组gb2312_uni_data[87][94]是在Windows操作系统下转换得到的。具体的做法是将国际汉字字符集中的所有字符按照一定的格式保存成文本文件,然后从文件中读出每个字符,调用函数MultiByteToWideChar(…)将其转换成Unicode编码,并将其保存。

  根据TrueType字库中字符的信息,显示或打印输出字符有两种途径:一种是调用FreeType的API函数得到相应字符的轮廓线,然后将其填充;另一种是调用FreeType的API函数直接得到字符的位图,再调用相应操作系统中的打点函数实现位图的显示。由于第二种方法实现起来比较简单,并且海图系统中的汉字不是很多,所以在海图程序中使用的是第二种方法。

  在获得相应汉字的字形位图信息的基础上,实现汉字打印输出功能的关键是如何使用PostScript语言描述相应汉字字形的位图信息。在程序的设计中,通过画1个像素长度的直线来实现点的输出,然后用一系列的点输出位图信息。其中,点的输出用PostScript语言表示为:

  x y moveto
  x+1 y lineto

  根据汉字横多竖少的特点,可以对以上产生的PostScript文件进行优化,如果N点在一条横线上,就直接画N长度的直线,用PostScript语言表示为:

  x y moveto
  x+N y line to

  这样,就将原来的N条PostScript语句转化为1条语句,从而减少了PostScript文件的长度。

7 结束语

  VxWorks实时操作系统的特点决定了在此操作系统中开发驱动程序的重要性。根据需要配置相应的设备,并实现硬件的驱动,是VxWorks系统中进行软件设计与开发的前提。本文介绍的电子海图系统打印功能的总体设计思想及实现方法,已在哈尔滨工程大学研制的某型电子海图系统的二次开发中得到应用。


支持(0中立(0反对(0单帖管理 | 引用 | 回复 回到顶部

返回版面帖子列表

实时操作系统VxWorks下电子海图系统打印功能的实现








签名