管理员
  
- 积分
- 165540
- 金钱
- 165540
- 注册时间
- 2010-12-1
- 在线时间
- 2117 小时
|
发表于 2011-10-23 09:24:24
|
显示全部楼层
#include "TXT.H"
#include "lcd.h"
//电子书操作函数
//还没有加入向前翻页的操作,等搞完毕业论文再弄了。。。
//正点原子@SCUT
//V1.2
//字体大小选择
u8 FSIZE=FONTSIZE16;//汉字大小,默认为16*16的
u32 FONT16CLUSTER=0;//16字体的首簇
u32 FONT12CLUSTER=0;//12字体的首簇
//Cluster 簇的序号 返回为该簇号所对应的扇区地址
//得到Cluster
unsigned long GetSysFileSector(u8 uoh,unsigned int Cluster)
{
unsigned long foffset=0;
unsigned int i;
if(uoh==16)foffset=FONT16CLUSTER;//得到unicode码的首簇
else if(uoh==12)foffset=FONT12CLUSTER;
i=Cluster;
while(i)
{
//printf("foffset:%d\n",foffset);
foffset=FAT_NextCluster(foffset);
i--;
}
//printf("final foffset:%d\n",foffset);
return fatClustToSect(foffset);
}
//code 字符指针开始
//从字库中查找出字模
//code 字符串的开始地址,ascii码
//mat 数据存放地址 FSIZE*2 bytes大小
void Get_HzMat(unsigned char *code,unsigned char *mat)
{
unsigned char qh,wh;
unsigned char i;
unsigned int sector,cluster,secoff;
unsigned long foffset;
if(*code<0xa1)if(*code++<0xa1)//非常用汉字
{
code--;
for(i=0;i<(FSIZE*2);i++)*mat++=0x00;//填充满格
return; //结束访问
}
qh=(*code++)-0xa1;
wh=(*code)-0xa1;
foffset=((unsigned long)94*qh+wh)*(FSIZE*2);//得到字库中的字节偏移量
sector=foffset/BytesPerSector; //得到总的完整的扇区数(不要写成(unsigned int )
secoff= (unsigned int) foffset%BytesPerSector;//扇区内的字节数偏移
wh=(unsigned char)sector%SectorsPerClust;
cluster=(unsigned int)sector/SectorsPerClust;//得到总的簇数
foffset=GetSysFileSector(FSIZE,cluster); //取汉字库的clusor簇数的扇区地址
if(BytesPerSector-secoff>=(FSIZE*2))//确定是否跨扇区?
{
SD_Read_Bytes(foffset+wh,mat,secoff,(FSIZE*2)); //读取(FSIZE*2)字节
}else
{
i=BytesPerSector-secoff; //读取的数据已跨扇区
SD_Read_Bytes(foffset+wh,mat,secoff,i);
if(++wh>SectorsPerClust)
{
wh=0;
foffset=GetSysFileSector(0,++cluster);//读取的数据已经跨簇
}
SD_Read_Bytes(foffset+wh,mat+i,0,(FSIZE*2)-i); //读取剩余的数据
}
}
//显示一个指定大小的汉字
//x,y:汉字的坐标
//font:汉字ASCII码
//mode:0,全填充写入.1,有效部分写入(适合在图片上叠加汉字)
void show_font(u8 x,u16 y,u8 *font,u8 mode)
{
u8 t1,t2;
u8 temp=0;
//扫描方式控制
LCD_WriteReg(0x0003,(1<<12)|(3<<4)|(1<<3) );//上至下,左至右
//面板大小设置 开辟1个FSIZE*FSIZE的空间
LCD_WriteReg(R80,x); //水平方向GRAM起始地址
LCD_WriteReg(R81,x+FSIZE-1); //水平方向GRAM结束地址
LCD_WriteReg(R82,y); //垂直方向GRAM起始地址
LCD_WriteReg(R83,y+FSIZE-1); //垂直方向GRAM结束地址
LCD_SetCursor(x,y); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
if(!mode)//非叠加模式
{
for(t1=0;t1<FSIZE;t1++)//共FSIZE个字节,每次读两个
{
temp=font[t1];
for(t2=0;t2<8;t2++)
{
if(temp&0x01)LCD->LCD_RAM=POINT_COLOR;
else LCD->LCD_RAM=BACK_COLOR;
temp>>=1;
}
temp=font[t1+FSIZE];
for(t2=0;t2<(FSIZE-8);t2++)//这里对16*16和其以下的字体合适
{
if(temp&0x01)LCD->LCD_RAM=POINT_COLOR;
else LCD->LCD_RAM=BACK_COLOR;
temp>>=1;
}
}
}else//叠加模式
{
for(t1=0;t1<FSIZE;t1++)//共FSIZE个字节,每次读两个
{
temp=font[t1];
for(t2=0;t2<8;t2++)
{
if(temp&0x01)TFT_DrawPoint(x+t1,y+t2);//画一个点
temp>>=1;
}
temp=font[t1+FSIZE];
for(t2=0;t2<(FSIZE-8);t2++)//这里对16*16和其以下的字体合适
{
if(temp&0x01)TFT_DrawPoint(x+t1,y+t2+8);//画一个点
temp>>=1;
}
}
}
//恢复原来的设置.
LCD_WriteReg(0x0003,(1<<12)|(3<<4)|(0<<3) );//左至右,上至下
//TFT_WR_CMD(0,0x00,0x04); //上至下,左至右 型扫描
LCD_WriteReg(R80, 0x0000); //水平方向GRAM起始地址
LCD_WriteReg(R81, 0x00EF); //水平方向GRAM结束地址
LCD_WriteReg(R82, 0x0000); //垂直方向GRAM起始地址
LCD_WriteReg(R83, 0x013F); //垂直方向GRAM结束地址
}
//在指定位置开始显示一个字符串
//非叠加方式显示
//支持自动换行
//(x,y):起始坐标
//str:字符串
//mode:模式:
//bit 0:1,叠加模式;0,覆盖模式
//bit 1:1,自动换行;0,不自动换行;
void Show_Str(u8 x,u16 y,u8*str,u8 mode)
{
u8 bHz=0; //字符或者中文
unsigned char *mat; //保存点陈内容
mat=jpg_buffer+512;//指向jpg_buffer的后半部分.前半部分用来存放文本文件了.
while(*str!=0)//数据未结束
{
if(!bHz)
{
if(*str>0x80)bHz=1;//中文
else //字符
{
if(x>(239-FSIZE/2))//换行
{
if(mode&0x02)//判断是不是要自动换行?
{
y+=FSIZE;
x=0;
}else return;
}
if(y>(319-FSIZE))break;//越界返回
if(*str==13)//换行符号
{
y+=FSIZE;
x=0;
str++;
}
else TFT_ShowChar(x,y,*str,FSIZE,mode&0x01);//有效部分写入
str++;
x+=FSIZE/2; //字符,为全字的一半
}
}else//中文
{
bHz=0;//有汉字库
if(x>(239-FSIZE))//换行
{
if(mode&0x02)//判断是不是要自动换行?
{
y+=FSIZE;
x=0;
}else return;
}
if(y>(319-FSIZE))break;//越界返回
Get_HzMat(str,mat);//得到点阵数据 (无字库不起动系统)
show_font(x,y,mat,mode&0x01); //显示这个汉字,空心显示
str+=2;
x+=FSIZE; //下一个汉字偏移
}
}
}
//在指定宽度的中间显示字符串
//如果字符长度超过了len,则用Show_Str显示
//len:指定要显示的宽度
//针对1616字体!!!
void Show_Str_Mid(u8 x,u16 y,u8*str,u8 mode,u8 len)
{
u16 strlenth=0;
strlenth=strlen((const char *)str);
strlenth*=8;
if(strlenth>len)Show_Str(x,y,str,mode);
else
{
strlenth=(len-strlenth)/2;
Show_Str(strlenth+x,y,str,mode);
}
}
typedef struct
{
u32* Lentable;
}LAST_TEXT;
LAST_TEXT txtprev;
//文本文件读取程序
//实现功能:把文件 FileName 打开.在液晶上显示出来
//打开txt/lrc文件
void Read_Book(FileInfoStruct *FileName)
{
u16 pointpos=0; //指针位置
unsigned long offlenth=0;//文件读取的大小
//unsigned long marklenth=0;//文件上一页的标记位
u16 x=0,y=0;
u8 *p=0; //指向txt文件
u8 temp[2]={0,0}; //换扇区使用
u8 bHz=0; //字符或者中文
unsigned char *mat; //保存点陈内容
u8 key;
u8 enout=0;//能否退出的标志
u8 keycnt=0;
u8 preven=0;//向上翻页的标志
u16  age_Cnt=0;//页码计数
txtprev.Lentable=(u32*)iclip;
mat=jpg_buffer+512; //指向jpg_buffer的后半部分.前半部分用来存放文本文件了.
if((FileName->F_Type&0xF0)==0)return;//不是TXT类型的文件
F_Open(FileName);//打开文件
txtprev.Lentable[0]=0;//读取了0个字节
LCD_Clear(WHITE);//清屏
POINT_COLOR=BLUE;//蓝色笔头
while(1)
{
//PRVIEW:
F_Read(FileName,jpg_buffer);//读取数据
if(preven)
{
pointpos=txtprev.Lentable[Page_Cnt]%BytesPerSector;
p=jpg_buffer+pointpos;//偏移后的了
printf("preven pointpos:%d\n",pointpos);
}
else p=jpg_buffer; //指向txt数据首地址
preven=0;
do
{
//printf("pointpos:%d\n",pointpos);
//printf("*p:%d\n\n",*p);
while(*p!=0)//数据未结束
{
if(!bHz)
{
if(*p>0x80)bHz=1;//中文字符
else //ASCII字符
{
if(x>(240-FSIZE/2)){y+=FSIZE;x=0;}//一行已满,换行
if(y>(320-FSIZE))break;//越界返回
if(*p==13)//换行符号
{
y+=FSIZE;
x=0;
p++;pointpos++;//跳过
}
else TFT_ShowChar(x,y,*p,FSIZE,1);
p++;pointpos++;
x+=FSIZE/2; //字符,为全字的一半
}
}else
{
bHz=0;//清除汉字标志
if(x>(240-FSIZE)){y+=FSIZE;x=0;}//换行
if(y>(320-FSIZE))break;//越界返回
//临界处理
if(pointpos==511)//保存上一扇区的最后一个字节,退出
{
temp[0]=*p; //记录最后的字节
break; //此扇区数据已经读完
}
if(temp[0])//上一次没有显示完
{
temp[1]=*p;//取第二扇区的第一个字节
Get_HzMat(temp,mat);//显示上一次的最后一个字 (无字库不起动系统)
p++;pointpos++;//偏移一个字节
temp[0]=0; //清除标记
}
else Get_HzMat(p,mat);//得到点阵数据 (无字库不起动系统)
show_font(x,y,mat,1); //显示这个汉字,空心显示
p+=2;pointpos+=2; //指针偏移
x+=FSIZE; //下一个汉字偏移
}
if(pointpos>511)break;
}
if(pointpos>=511)break;//一个扇区读取完毕,直接跳出,读下一个扇区,防止停顿
Pen_Point.Key_Sta=Key_Up;//释放显示期间的触发
enout=0; //退出使能标志不使能
key=0;
while(1) //是否显示下一屏数据
{
if((Pen_Point.Key_Sta==Key_Down||NPEN)&&Pen_Point.Key_LSta)key=Touch_To_Num(7);//扩展按键扫描
if(PEN)//按键松开了,状态改变(状态机)
{
Pen_Point.Key_LSta=1;
Pen_Point.Key_Sta=Key_Up;
}
/*if(key==KEY_PREV)//向上翻页
{
Pen_Point.Key_LSta=Key_Up;
if(Page_Cnt)
{
Page_Cnt--;
offlenth=txtprev.Lentable[Page_Cnt]/BytesPerSector;//得到现在已经读取了的扇区数
printf("dec offlenth:%d\n",offlenth);
printf("p offlenth:%d\n\n",txtprev.Lentable[Page_Cnt]);
F_Open(FileName);
while(offlenth)
{
F_Read(FileName,jpg_buffer);
offlenth--;//增加一个扇区
}
offlenth=txtprev.Lentable[Page_Cnt];//指向下一个扇
temp[0]=0;
bHz=0;
x=0;y=0;
preven=1;
LCD_Clear(WHITE);//清屏
goto  RVIEW;
}
}*/
if(key==KEY_NEXT)//向下翻页
{
Pen_Point.Key_LSta=Key_Up;
keycnt=0;
if(enout){if(Is_In_Area(200,300,239,319))return;}//退出文件阅读
if(offlenth+pointpos+1>=FileName->F_Size)return;//文件读取结束(长度结束)
if(y>(320-FSIZE)){x=0;y=0;}//非结尾返回,屏幕已满,清屏
LCD_Clear(WHITE);//清屏
//Page_Cnt++;
//txtprev.Lentable[Page_Cnt]=offlenth+pointpos+1;//得到当前所读取的字节数
//printf("n offlenth:%d\n\n",txtprev.Lentable[Page_Cnt]);
break;
}else if(key==KEY_FUNC)//按中中间区域了
{
Pen_Point.Key_LSta=Key_Down;//使能下次进入
keycnt++;
if(keycnt>=20)
{
keycnt=0;
enout=1;//使能退出
POINT_COLOR=RED;
TFT_Fill(0,298,239,319,0X81BF);//填充底部颜色
Show_Str(203,300,"返回",0x01); //叠加模式,非自动换行
POINT_COLOR=BLUE;
}
}
key=0;//清除此次按键
delay_ms(5);
}
}while(pointpos<511);
offlenth+=pointpos+1;//文件长度累加
pointpos=0;//清除指针计数器
}
}
|
|