使用Tslib在触摸屏上显示汉字

终于到了在触摸屏上显示汉字了,真正写代码、测试的时间是1天,在此之前的一切准备、学习花费约2周到3周时间。而为了获取触摸屏上显示的图像,花费约2天。由于网络驱动已经接近于放弃状态,NFS用不了,只好用U盘来回复制(即使没有耐心也必须有耐心了)。明明在内核中选择了支持NTFS格式的读写,但却不能将开发板上的文件复制到U盘,而用另一个FAT32格式的另一牌子的U盘,开发板死活认不出来,网上的资料说要修改代码,我又懒得去改。无奈之下,只好格式化那个NTFS的U盘,结果,这篇文章拖到现在才发表。

 

郑重说明:

本文作者在本文及前面的文章中没有提及作者的工作内容、工作时间、业余时间及业余生活,因为在这些文章中涉及那些工作、生活内容是不明智的。这些文章并没有任何迹象表明作者没有工作、没有业余生活,也并没有表明作者只生活在写代码中。

 

免责声明:

本文是作者在研究过程中的一篇文章,本着互联网共享、自由(free,应该不是“免费”)之精神发布于此。本文使用的是Tslib中的代码,并在此基础上添加自己的代码,关于Tslib,作者已经写过很多篇相关的文章了,这里公布的仅仅是自己添加的代码。作者对文中代码没有任何义务,仅因为Tslib使用GPL协议,本文作者必须使用这个协议。作者才疏学浅,孤陋寡闻,能力有限,文中错误的地方,欢迎在文后留言,趁作者还有激情研究之时,大家一直探讨,共同学习,天天向上。

再声明一点,本文作者在S3C2440芯片的开发板上,使用最新下载的tslib,使用汉字字库HZK16、HZK24*,通过自己写的代码,在开发板自带的触摸屏上显示汉字。但是,并没有在其它的测试环境、平台下进行测试。

 

关于汉字显示的算法(其实没啥算法)、步骤已经在前面的文章说了很多了,此处不再提及。

 

由于还没有对autotool进行研究,而Tslib又使用这个工具管理代码,因此不懂如何添加新文件,如果让新文件也能编译。只好在原来的原来的文件中添加代码了。添加的代码的函数声明在fbutils.h中,函数定义在fbutils.c文件中,测试代码在ts_test.c中。

代码修改了约三次,基本上都是一些结构上的调整,就不说那些体面的话了。至于真正改动之处,只在最底层的显示字符的代码修改了几个地方,就是将原来的乘法改为移位,而对其它一些地方的乘法及移位测试时,发现没什么区别,因此保留乘法。举一例,如

offset = (*ascii - 0x20 ) * 16;

就没有改为

offset = (*ascii - 0x20 ) << 4;

前者更能让人明白这里的ASCII字符在字库数组中占用16字节,而左移4位,的确让人不知道有什么含义。

 

已知bug:

1、不在GB2312范围之内的汉字不能正常显示——这是废话,正如在en_US字符集下显示中文一样。

2、UCDOS的HZK24*系列字库文件没有中文字符,像“◆ □ ■ △ ▲”等在16点阵下显示正常,而在24点阵中显示失败(乱码或其它汉字),网上找不到包括完整的中文字符的字库,另外,不知道使用UCDOS的字库算不算侵权(这些东西都可以在网络下载)。

 

函数声明:

/* new add by Late Lee */
/* ascii code */
void put_string_ascii(int x, int y, char *s, unsigned colidx);
void put_string_center_ascii(int x, int y, char *s, unsigned colidx);
/* cineses character */
void put_string_hz(FILE *fp, int x, int y, unsigned char *s, unsigned colidx);
void put_string_center_hz(FILE *fp, int x, int y, unsigned char *s, unsigned colidx);
/* chineses character & ascii */
void put_font(FILE *fp, int x, int y, unsigned char *s, unsigned colidx);
void put_font_center(FILE *fp, int x, int y, unsigned char *s, unsigned colidx);
/* end of new add */

 

测试代码(ts_test.c):

static FILE *fp;  /* HZK file pointer by Late Lee */
#define HZK "HZK/HZK16" /* HZK16 or HZK24K/HZK24S */

static void refresh_screen ()
{
……
 /* just a test */
 unsigned char incode[] = "▲!ADC■测镕试◎示例"; // 注:“镕”字不在GB2312范围之内,不能正常显示。
 int y = yres/4+50;
 put_string_ascii(0, y, "Powered by Late Lee", 9);
 put_string_hz(fp, 0, y+30, "波神留我看斜阳听取蛙声一片", 2);
 put_font(fp, 0, y+56, incode, 5);
 /* end of the test */

……
}
 

 

 

关键的代码(fbutils.c):

/* new add by Late Lee 2011-05-30*/
//#define HZK24
#ifdef HZK24  /* 24 */
#include  "ascii24.h"
#define   ASCII_CODE   ascii24
#define   FONT_SIZE     24                         /* size: 24 */
#else         /* 16 */
#include  "ascii16.h"
#define  ASCII_CODE  ascii16
#define  FONT_SIZE    16                         /* size: 16 */
#endif


#define BYTES                (FONT_SIZE/ 8)                   /* for HZ: 3 bytes  2 bytes*/
#define BUF_SIZE          (BYTES * FONT_SIZE)        /* HZ buff 3*24 = 72 bytes 2*16 = 32 bytes */

#define ASCII_BYTES     (BYTES- 1)                    /* 2 1*/
#define ASCII_SIZE       (FONT_SIZE * ASCII_BYTES)      /* ASCII buffer: 24*2 = 48 bytes 16 * 1 = 16 bytes */
#define ASCII_WIDTH    (FONT_SIZE/ 2)                         /* ASCII: 16*8 24*12 */

/* end here Late Lee*/

/*****************************************************************************
*           new add by Late Lee 2011-05-30
*****************************************************************************/


/**
 * __display_ascii - Display an ASCII code on touch screen
 * @x: Column
 * @y: Row
 * @ascii: Which ASCII code to display 
 * @colidx: Color index(?)
 * This routine display an ASCII code that stored in an array(eg, ASCII_CODE).
 * 16x8 ASCII code takes 1 byte, 24*12 ASCII code takes 2 bytes, so we need 
 * -ASCII_BYTES-.
 */

static  void __display_ascii( int x,  int y,  char *ascii,  unsigned colidx)
{
         int i, j, k;
         unsigned  char *p_ascii;
         int offset;        
        
        offset = (*ascii -  0x20 ) * ASCII_SIZE;  /* find the code in the array */
        p_ascii = ASCII_CODE + offset;

         for(i= 0;i<FONT_SIZE;i++)
                 for(j= 0;j<ASCII_BYTES;j++)
                         for(k= 0;k< 8;k++)
                                 if( p_ascii[i*ASCII_BYTES+j] & ( 0x80>>k) )
                                 //if(*( p_ascii + i*ASCII_BYTES+j) & (0x80>>k))
                                        pixel (x + j* 8 + k, y + i, colidx);
}

/**
 * put_string_ascii - Display an ASCII string on touch screen
 * @x: Column
 * @y: Row
 * @s: Which string to display
 * @colidx: Color index
 */

void put_string_ascii( int x,  int y,  char *s,  unsigned colidx)
{
         while (*s !=  0) {
                __display_ascii(x, y, s, colidx);
                x += ASCII_WIDTH;
                s++;
        }
}

/* not test */
void put_string_center_ascii( int x,  int y,  char *s,  unsigned colidx)
{
        size_t sl = strlen (s);
        put_string_ascii (x - (sl /  2) * ASCII_WIDTH,
                    y - FONT_SIZE /  2, s, colidx);
}

/**
 * __display_font_16 - Display a 16x16 (chinese) character on touch screen
 * @fp: File pointer points to HZK(ie, HZK16)
 * @x: Column
 * @y: Row
 * @font: Which (chinese) character to display
 * @colidx: Color index
 * This routine ONLY display 16*16 character.
 * Every character takes two bytes, we show the first 8 bits, then the second 8 bits,
 * then the whole world will be shown before us.
 */

static  void __display_font_16 (FILE *fp,  int x,  int y,  unsigned  char *font,  unsigned colidx)
{
         int i, j, k;
         unsigned  char mat[BUF_SIZE]={ 0};
         int qh,wh;
         unsigned  long offset;
        qh = *font   -  0xa0;
        wh = *(font+ 1) -  0xa0;
        offset = (  94*(qh- 1) + (wh- 1) ) * BUF_SIZE;  /* offset of the character in HZK */

         /* read it */
        fseek(fp,offset,SEEK_SET);
        fread(mat,BUF_SIZE, 1,fp);

         /* show it */
         for(i= 0;i<FONT_SIZE;i++)
                 for(j= 0;j<BYTES;j++)
                         for(k= 0;k< 8;k++)
                                 if(mat [i*BYTES+j] & ( 0x80>>k))
                                        pixel (x + j* 8 + k, y + i, colidx);
}

/**
 * __display_font_24 - Display a 24x24 (chinese) character on touch screen
 * @fp: File pointer points to HZK(ie, HZK24)
 * @x: Column
 * @y: Row
 * @font: Which (chinese) character to display
 * @colidx: Color index
 */

static  void __display_font_24 (FILE *fp,  int x,  int y,  unsigned  char *font,  unsigned colidx)
{
         unsigned  int i, j;
         unsigned  char mat[FONT_SIZE][BYTES]={{ 0}};
         int qh,wh;
         unsigned  long offset;
        qh = *font   -  0xaf;
        wh = *(font+ 1) -  0xa0;
        offset = (  94*(qh- 1) + (wh- 1) ) * BUF_SIZE;

        fseek(fp,offset,SEEK_SET);
        fread(mat,BUF_SIZE, 1,fp);

         for(i= 0;i<FONT_SIZE;i++)
                 for(j= 0;j<FONT_SIZE;j++)
                         if( mat[j][i>> 3] & ( 0x80>>(i& 7)) )
                         // if ( mat[j][i/8] & (0x80>>i%8) ) /* org */
                                pixel (x + j, y + i, colidx);
}

/**
 * put_string_hz - Display a (chinese) character string on touch screen
 * @fp: File pointer points to HZK(ie, HZK24 or HZK16)
 * @x: Column
 * @y: Row
 * @s: Which string to display(must be 'unsigned char*')
 * @colidx: Color index
 */

void put_string_hz (FILE *fp,  int x,  int y,  unsigned  char *s,  unsigned colidx)
{        
         while (*s !=  0) {
                 #ifdef HZK24
                __display_font_24 (fp, x, y, s, colidx);  /* for HZK24 */
                 #else
                __display_font_16 (fp, x, y, s, colidx);
                 #endif
                x += FONT_SIZE;
                s +=  2;         /* 2 bytes */
        }
}

/* not test */
void put_string_center_hz (FILE *fp,  int x,  int y,  unsigned  char *s,  unsigned colidx)
{
        size_t sl = strlen (( char *)s);
        put_string_hz (fp, x - (sl/ 2) * FONT_SIZE, y - FONT_SIZE/ 2, s, colidx);
}

/**
 * put_font - Display an ASCII or/and (chinese) character string on touch screen
 * @fp: File pointer points to HZK(ie, HZK24 or HZK16)
 * @x: Column
 * @y: Row
 * @s: Which string to display
 * @colidx: Color index
 */

void put_font(FILE *fp,  int x,  int y,  unsigned  char *s,  unsigned colidx)
{
         while (*s !=  0) {
                 if ( (*s> 0xa0) && (*(s+ 1)> 0xa0) ) {
                         #ifdef HZK24
                        __display_font_24 (fp, x, y, s, colidx);          /* for HZK24 */
                         #else
                        __display_font_16 (fp, x, y, s, colidx);         /* for HZK16 */
                         #endif
                        x += FONT_SIZE;
                        s +=  2;         /* 2 bytes */
                }  else {
                        __display_ascii (x, y, ( char *)s, colidx);
                        x += ASCII_WIDTH;
                        s++;         /* 1 byte */
                }
        }
}
/* not test */
void put_font_center(FILE *fp,  int x,  int y,  unsigned  char *s,  unsigned colidx)
{
        size_t sl = strlen (( char *)s);
        put_font (fp, x - (sl/ 2) *  16, y -  16/ 2, s, colidx);
}

 

关于截图:

使用fb2png(可通过google搜索“fb2png”,我是很辛苦才找到的),交叉编译,在开发板上执行如下命令: 

fb2png /dev/fb0 filename.png 5 800 600 24

 

实际中使用的命令为:

fb2png /dev/fb0 filename.png 5 240 320 16

 

效果图如下(由于图片已经有了本人的大名,故不打水印了):

 

 

 

 

效果图亦可以参见:

http://www.latelee.org/yetanothertest/display-hz-on-touch-screen.html

 

临时整理的工程目录压缩包:

能显示汉字的tslib压缩包

 

下一计划是ADC和TS驱动。

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页