mian.c
//-----------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <sys/unistd.h>
#include <io.h>
#include <string.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
#include "sys/alt_irq.h"
#include "lcd.h"
#include "tsp.h"
/*************************************************/
/*************************************************/
alt_u8 myButton, mLED;
int main(void)
{
int i;
alt_u16 *pPic;
alt_u16 temp, color;
printf("Exp14 TouchScreen Test!\n");
LCD_IO_Init();
LCD_On_Off(1);
TS_GetXY(&temp, &temp);
TSP_Test();
return 0;
}
//----------------------------------------------------------------------------
lcd.c
//--------------------------------------------------------------------------
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
#include "lcd.h"
/************************************************/
void LCD_IO_Init(void)
{
IOWR_ALTERA_AVALON_PIO_DATA(LCD_RD_BASE, 1); //rd = 1
IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 1); //wr = 1
IOWR_ALTERA_AVALON_PIO_DATA(LCD_CS_BASE, 1); //cs = 1
IOWR_ALTERA_AVALON_PIO_DIRECTION(LCD_DATA_BASE, OUT);
}
void LCD_Write(alt_u8 addr, alt_u16 dat)
{
IOWR_ALTERA_AVALON_PIO_DATA(LCD_ADDR_BASE, addr); //output addr
IOWR_ALTERA_AVALON_PIO_DATA(LCD_DATA_BASE, dat); //output dat
IOWR_ALTERA_AVALON_PIO_DATA(LCD_CS_BASE, 0); //cs = 0
IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 0); //wr = 0
IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 1); //wr = 1
IOWR_ALTERA_AVALON_PIO_DATA(LCD_CS_BASE, 1); //cs = 1
}
void LCD_On_Off(alt_u8 on_off)
{
LCD_Write(LCD_DISP, on_off);
}
void FillScreen(alt_u8 ad_mode, alt_u16 color)
{
alt_u32 i;
LCD_Write(LCD_X, 0);
LCD_Write(LCD_Y, 0);
LCD_Write(LCD_AS, ad_mode); //ad_mode为操作模式、M1M0=00为字节操作模式,M1M0=00为行操作模式,M1M0=10为列操作模式
for(i=0; i<LCD_W*LCD_H;i++)
LCD_Write(LCD_DAT, color);
}
/*********************************************************************/
/*************************************************************/
void Draw_Pixel(alt_u16 x, alt_u16 y, alt_u16 color) //在(x,y)位置画点
{
LCD_Write(LCD_X, x);
LCD_Write(LCD_Y, y);
LCD_Write(LCD_DAT, color);
}
void DrawLine(alt_u16 x1, alt_u16 y1, alt_u16 x2, alt_u16 y2, alt_u16 color) //从(x1,y1)到(x2,y2)的线段
{
int Lx, Ly, Cx, Cy, XER = 0,YER = 0, DTC;
alt_u16 i = 0;
Lx = x2 - x1;
Ly = y2 - y1;
if(Lx > 0)
Cx = 1;
else if(Lx < 0)
Cx = -1;
if(Ly > 0)
Cy = 1;
else if(Ly < 0)
Cy = -1;
if(Lx == 0) //Vertical Line
{
if(Ly == 0)
Draw_Pixel(x1, y1, color);
else
{
do
{
Draw_Pixel(x1, y1, color);
y1 += Cy;
}
while(y1 != y2);
Draw_Pixel(x1, y1, color);
}
return;
}
else if(Ly == 0) //Horizontal Line
{
do
{
Draw_Pixel(x1, y1, color);
x1 += Cx;
}
while(x1 != x2);
Draw_Pixel(x1, y1, color);
return;
}
Lx = fabs(Lx);
Ly = fabs(Ly);
if(Ly>Lx)
DTC = Ly;
else
DTC = Lx;
for(i=0; i<=DTC+1; i++)
{
Draw_Pixel(x1, y1, color);
XER += Lx;
YER += Ly;
if(XER>DTC)
{
XER -= DTC;
x1 += Cx;
}
if(YER>DTC)
{
YER -= DTC;
y1 += Cy;
}
}
}
void DrawRect(alt_u16 x, alt_u16 y, alt_u16 xl, alt_u16 yl, alt_u16 color) //画矩形框
{
alt_u16 i;
LCD_Write(LCD_AS, 1);
//横线顶端
LCD_Write(LCD_X, x);
LCD_Write(LCD_Y, y);
for(i=0; i<xl; i++)
LCD_Write(LCD_DAT, color);
//横线低端
LCD_Write(LCD_X, x);
LCD_Write(LCD_Y, y+yl-1);
for(i=0; i<xl; i++)
LCD_Write(LCD_DAT, color);
//横线左端
LCD_Write(LCD_AS, 2);
LCD_Write(LCD_X, x);
LCD_Write(LCD_Y, y);
for(i=0; i<yl; i++)
LCD_Write(LCD_DAT, color);
//横线低端
LCD_Write(LCD_X, x+xl-1);
LCD_Write(LCD_Y, y);
for(i=0; i<yl; i++)
LCD_Write(LCD_DAT, color);
}
void DrawFillRect(alt_u16 x, alt_u16 y, alt_u16 xl, alt_u16 yl, alt_u16 color) //(x,y),(x1,y1),画实心矩形框
{
alt_u16 i, j;
LCD_Write(LCD_AS, 1);
for(j=y; j<y+yl;j++)
{
LCD_Write(LCD_X, x);
LCD_Write(LCD_Y, j);
for(i=0; i<xl; i++)
LCD_Write(LCD_DAT, color);
}
}
void DrawEllipse(alt_u16 xp, alt_u16 yp, alt_u16 a, alt_u16 b, alt_u16 color) //画椭圆
{ //----(xp,yp)和(a,b)分别为两焦点坐标
alt_u16 x, y;
float tmp;
for(x=0; x<=a; x++)
{
tmp = x;
tmp /= a;
y = b * sqrt(1 - tmp * tmp) + 0.5;
Draw_Pixel(xp + x, yp + y, color);
Draw_Pixel(xp + x, yp - y, color);
Draw_Pixel(xp - x, yp + y, color);
Draw_Pixel(xp - x, yp - y, color);
}
for(y=0; y<=b; y++)
{
tmp = y;
tmp /= b;
x = a * sqrt(1 - tmp * tmp) + 0.5;
Draw_Pixel(xp + x, yp + y, color);
Draw_Pixel(xp + x, yp - y, color);
Draw_Pixel(xp - x, yp + y, color);
Draw_Pixel(xp - x, yp - y, color);
}
}
void DrawCross(alt_u16 xp, alt_u16 yp, alt_u16 len, alt_u16 color) //画十字光标
{ //--(xp,yp)光标中心位置,len光标长度
if( xp < len ) xp = len;
if( xp >= LCD_W - len ) xp = LCD_W - len - 1;
if( yp < len ) yp = len;
if( yp >= LCD_H - len ) yp = LCD_H - len - 1;
DrawLine(xp-len, yp-1, xp+len, yp-1, color);
DrawLine(xp-len, yp, xp+len, yp, color);
DrawLine(xp-len, yp+1, xp+len, yp+1, color);
DrawLine(xp-1, yp-len, xp-1, yp+len, color);
DrawLine(xp, yp-len, xp, yp+len, color);
DrawLine(xp+1, yp-len, xp+1, yp+len, color);
}
/****************【基本显示字符、汉字函数】**********/
void DisplayChar(char Char, alt_u16 xp, alt_u16 yp, alt_u16 fcolor, alt_u16 bcolor) //显示任意字符
{
alt_u8 i,j;
alt_u8 *Font_Addr = (alt_u8 *)(NOR_FLASH_BASE + 0x7c0000 + ((Char)<<4));
alt_u8 ft = 0;
LCD_Write(LCD_AS, 1);
for(i=0; i<16; i++)
{
LCD_Write(LCD_X, xp);
LCD_Write(LCD_Y, yp+i);
ft = Font_Addr[i];
for(j=0; j<8; j++)
{
if(ft & 0x80)
LCD_Write(LCD_DAT, fcolor);
else
LCD_Write(LCD_DAT, bcolor);
ft <<= 1;
}
}
}
void DisplayHanzi(alt_u16 Unicode, alt_u16 xp, alt_u16 yp, alt_u16 fcolor, alt_u16 bcolor) //显示任意汉字
{
alt_u8 i,j;
alt_u16 ft;
alt_u16 *Font_Addr = (alt_u16 *)(NOR_FLASH_BASE + 0x7c0000 + ((Unicode-0x3bbf-(Unicode>>8)*0xa2)<<5) + 0x01000);
LCD_Write(LCD_AS, 1);
for(i=0; i<16; i++)
{
LCD_Write(LCD_X, xp);
LCD_Write(LCD_Y, yp+i);
ft = SWAP16(Font_Addr[i]);
for(j=0; j<16; j++)
{
if(ft & 0x8000)
LCD_Write(LCD_DAT, fcolor);
else
LCD_Write(LCD_DAT, bcolor);
ft <<= 1;
}
}
}
alt_u16 SizeofString(alt_u8 *str) //求取字符串长度
{
alt_u16 len = 0;
while(str[len++]);
return len-1;
}
//显示任意字符串(中文为宋体,英文为8×16点阵)
void DisplayAnyString(alt_u8 *Str, alt_u16 xp, alt_u16 yp, alt_u16 fcolor, alt_u16 bcolor)
{ //--Str为指针,指向带显示字符;(xp,yp)为显示坐标,fcolor为字体颜色,bcolor为背景颜色
alt_u16 i;
alt_u16 str_len = SizeofString(Str);
for(i=0; i<str_len; i++)
{
if(Str[i] < 0x80)
{
if(xp > LCD_W - 8)
{
xp = 0;
yp += 16;
}
if(Str[i] == 0x0d) //回车
xp = 0;
else if(Str[i] == 0x0a) //换行
yp += 16;
else
{
DisplayChar(Str[i], xp, yp, fcolor, bcolor);
xp += 8;
}
}
else
{
if(xp > LCD_W - 16)
{
xp = 0;
yp += 16;
}
DisplayHanzi((Str[i]<<8)|Str[i+1], xp, yp, fcolor, bcolor);
xp += 16;
i++;
}
}
}
void Display_Pic(alt_u16 *pic, alt_u16 xp, alt_u16 yp, alt_u16 w, alt_u16 h)
{ //Pic指向带显示码,(xp,yp)为初始坐标,w、h为宽度和高度,依次向左向下
alt_u16 i, j;
LCD_Write(LCD_AS, 1);
for(i=0; i<h; i++)
{
LCD_Write(LCD_X, xp);
LCD_Write(LCD_Y, yp+i);
for(j=0; j<w; j++)
LCD_Write(LCD_DAT, *pic++);
}
}
//----------------------------------------------------------------
LCD.h
//--------------------------------------------------------------------
#ifndef __LCD_H__
#define __LCD_H__
/************************************************/
#define LCD_W 800
#define LCD_H 600
#define OUT 0xffff
#define IN 0x0000
#define LCD_X 0 //-----列地址低位寄存器X
#define LCD_Y 1 //-----行地址高位寄存器Y
#define LCD_AS 2 //-----操作模式寄存器
#define LCD_DISP 3 //----LCD显示控制器
#define LCD_RDY 4 //----
#define LCD_DAT 7 //----读/写LCD显示数据
#define COLOR_BLACK 0x0000
#define COLOR_WHITE 0xFFFF
#define COLOR_RED 0xF800
#define COLOR_GREEN 0x07E0
#define COLOR_BLUE 0x001F
#define COLOR_YELLOW 0xFFE0
#define COLOR_PURPLE 0x8010
#define COLOR_ORANGE 0xFC00
#define COLOR_CYAN 0x87FF //---cyan蓝绿色
#define SWAP16(x) ((x<<8) | (x>>8))
/************************************************/
void LCD_IO_Init(void);
void LCD_Write(alt_u8 addr, alt_u16 dat);
void LCD_On_Off(alt_u8 on_off);
void FillScreen(alt_u8 ad_mode, alt_u16 color);
void Draw_Pixel(alt_u16 x, alt_u16 y, alt_u16 color);
void DrawLine(alt_u16 x1, alt_u16 y1, alt_u16 x2, alt_u16 y2, alt_u16 color);
void DrawRect(alt_u16 x, alt_u16 y, alt_u16 xl, alt_u16 yl, alt_u16 color);
void DrawFillRect(alt_u16 x, alt_u16 y, alt_u16 xl, alt_u16 yl, alt_u16 color);
void DrawEllipse(alt_u16 xp, alt_u16 yp, alt_u16 a, alt_u16 b, alt_u16 color);
void DrawCross(alt_u16 xp, alt_u16 yp, alt_u16 len, alt_u16 color);
void DisplayChar(char Char, alt_u16 xp, alt_u16 yp, alt_u16 fcolor, alt_u16 bcolor);
void DisplayHanzi(alt_u16 Unicode, alt_u16 xp, alt_u16 yp, alt_u16 fcolor, alt_u16 bcolor);
void DisplayAnyString(alt_u8 *Str, alt_u16 xp, alt_u16 yp, alt_u16 fcolor, alt_u16 bcolor);
void Display_Pic(alt_u16 *pic, alt_u16 xp, alt_u16 yp, alt_u16 w, alt_u16 h);
/************************************************/
#endif
//-------------------------------------------------------------------
TSP.c
//-------------------------------------------------------------------
#include <sys/unistd.h>
#include <io.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "tsp.h"
#include "lcd.h"
/**************************************/
alt_u16 Min_X_Ad, Max_X_Ad;
alt_u16 Min_Y_Ad, Max_Y_Ad;
/**************************************/
void TS_GetXY(alt_u16 *x, alt_u16 *y) //获取当前触摸点坐标
{
int i;
alt_u16 TS_X_Ad, TS_Y_Ad;
for(i=0; i<2; i++)
TS_X_Ad = TS_Read_X_Ad(0xd3);
TS_X_Ad = 0;
for(i=0; i<4; i++)
TS_X_Ad += TS_Read_X_Ad(0xd3);
TS_X_Ad >>= 2;
for(i=0; i<2; i++)
TS_Y_Ad = TS_Read_Y_Ad(0x93);
TS_Y_Ad = 0;
for(i=0; i<4; i++)
TS_Y_Ad += TS_Read_Y_Ad(0x93);
TS_Y_Ad >>= 2;
ADC_to_XY(TS_X_Ad, TS_Y_Ad, x, y);
TS_Read_X_Ad(0xd0);
}
void ADC_to_XY(alt_u16 xad, alt_u16 yad, alt_u16 *x, alt_u16 *y) //AD值转换成XY坐标
{
alt_u16 tmp;
if(xad < Min_X_Ad)
xad = Min_X_Ad;
else if(xad > Max_X_Ad)
xad = Max_X_Ad;
tmp = Max_X_Ad - Min_X_Ad;
if(tmp == 0)
tmp = 1;
*x = (xad - Min_X_Ad) * LCD_W / tmp;
if(yad < Min_Y_Ad)
yad = Min_Y_Ad;
else if(yad > Max_Y_Ad)
yad = Max_Y_Ad;
tmp = Max_Y_Ad - Min_Y_Ad;
if(tmp == 0)
tmp = 1;
*y = (yad - Min_Y_Ad) * LCD_H / tmp;
}
#define TS_Delay1() usleep(5)
#define TS_Delay2() usleep(5)
#define TS_Delay3() usleep(25)
alt_u16 TS_Read_X_Ad(alt_u8 cmd) //读取触摸平控制器X方向AD值
{
alt_u16 i;
alt_u16 dat = 0;
TS_CS_Low;
TS_DCLK_Low;
TS_Delay1();
for(i=0; i<8; i++)
{
if(cmd & 0x80)
TS_DOUT_High;
else
TS_DOUT_Low;
TS_Delay1();
TS_DCLK_High;
cmd <<= 1;
TS_Delay1();
TS_DCLK_Low;
}
TS_Delay3();
for(i=0; i<13; i++)
{
TS_DCLK_High;
dat <<= 1;
if(TS_DIN)
dat |= 1;
TS_Delay2();
TS_DCLK_Low;
TS_Delay2();
}
TS_CS_High;
return dat & 0xfff;
}
alt_u16 TS_Read_Y_Ad(alt_u8 cmd) //读取触摸平控制器Y方向AD值
{
alt_u16 i;
alt_u16 dat = 0;
TS_CS_Low;
TS_DCLK_Low;
TS_Delay2();
for(i=0; i<8; i++)
{
if(cmd & 0x80)
TS_DOUT_High;
else
TS_DOUT_Low;
TS_Delay1();
TS_DCLK_High;
cmd <<= 1;
TS_Delay1();
TS_DCLK_Low;
}
TS_Delay3();
for(i=0; i<13; i++)
{
TS_DCLK_High;
dat <<= 1;
if(TS_DIN)
dat |= 1;
TS_Delay2();;
TS_DCLK_Low;
TS_Delay2();
}
TS_CS_High;
return (0xfff - (dat & 0xfff));
}
//触摸屏校
void TS_Calibrate(void)
{
alt_u8 PenTouchCount = 0;
alt_u16 TchX[4], TchY[4];
alt_u16 i, xp, yp, x, y;
float min, max;
alt_u32 AD_X, AD_Y;
FillScreen(1, COLOR_WHITE);
while(!TSP_State())
usleep(50000);
while(PenTouchCount < 4)
{
switch(PenTouchCount)
{
case 0: { xp = 20; yp = 20; break; }
case 1: { xp = 20; yp = LCD_H-20; break; }
case 2: { xp = LCD_W-20; yp = LCD_H-20; break; }
case 3: { xp = LCD_W-20; yp = 20; break; }
default : break;
}
DrawCross(xp, yp, 20, COLOR_RED);
if(!TSP_State())
{
for(i=0; i<2; i++)
{
TS_Read_X_Ad(0xd3);
TS_Read_Y_Ad(0x93);
}
AD_X = AD_Y = 0;
#define NN 16
for(i=0; i<NN; i++)
AD_X += TS_Read_X_Ad(0xd3);
for(i=0; i<NN; i++)
AD_Y += TS_Read_Y_Ad(0x93);
TchX[PenTouchCount] = AD_X / NN;
TchY[PenTouchCount] = AD_Y / NN;
TS_GetXY(&x, &y);
DrawCross(xp, yp, 20, COLOR_BLUE);
while(!TSP_State())
usleep(50000);
DrawCross(xp, yp, 20, COLOR_WHITE);
PenTouchCount++;
}
usleep(10000);
}
//计算X方向最小值和最大值
min = (TchX[0] + TchX[1]) / 2;
max = (TchX[2] + TchX[3]) / 2;
Min_X_Ad = min - (max - min) / 30;
Max_X_Ad = max + (max - min) / 30;
//计算Y方向最小值和最大值
min = (TchY[0] + TchY[3]) / 2;
max = (TchY[1] + TchY[2]) / 2;
Min_Y_Ad = min - (max - min) / 22;
Max_Y_Ad = max + (max - min) / 22;
}
//-------------------------------------------------
#define XP_ERROR 5
#define NO_ERR_TIMES 2
void TSP_Test(void)
{
alt_u16 old_x, old_y, X_Pos, Y_Pos;
old_x = old_y = 0;
TS_Calibrate();
while(1)
{
if(!TSP_State())
{
usleep(5000);
old_x = X_Pos;
old_y = Y_Pos;
TS_GetXY(&X_Pos, &Y_Pos);
DrawCross(old_x, old_y, 10, COLOR_WHITE);
DrawCross(X_Pos, Y_Pos, 10, COLOR_BLUE);
}
usleep(10000);
}
}
//----------------------------------------------------------------------------------
TSP.h
//----------------------------------------------------------------------------------
#ifndef _TSP_H_
#define _TSP_H_
#define MAX_X_POSITION 639
#define MAX_Y_POSITION 479
#define TOUCHPEN_STATE (rPDATG & 0x01)
#define TS_CS_Low IOWR_ALTERA_AVALON_PIO_DATA(TSP_CS_BASE, 0)
#define TS_CS_High IOWR_ALTERA_AVALON_PIO_DATA(TSP_CS_BASE, 1)
#define TS_DCLK_Low IOWR_ALTERA_AVALON_PIO_DATA(TSP_CLK_BASE, 0)
#define TS_DCLK_High IOWR_ALTERA_AVALON_PIO_DATA(TSP_CLK_BASE, 1)
#define TS_DOUT_Low IOWR_ALTERA_AVALON_PIO_DATA(TSP_DO_BASE, 0)
#define TS_DOUT_High IOWR_ALTERA_AVALON_PIO_DATA(TSP_DO_BASE, 1)
#define TS_DIN IORD_ALTERA_AVALON_PIO_DATA(TSP_DI_BASE)
#define TSP_State() IORD_ALTERA_AVALON_PIO_DATA(TSP_INT_BASE)
/*****************************************/
extern alt_u16 Min_X_Ad, Max_X_Ad;
extern alt_u16 Min_Y_Ad, Max_Y_Ad;
/*****************************************/
void TS_GetXY(alt_u16 *x, alt_u16 *y); //获取当前触摸点坐标
void ADC_to_XY(alt_u16 xad, alt_u16 yad, alt_u16 *x, alt_u16 *y); //AD值转换成XY坐标
alt_u16 TS_Read_X_Ad(alt_u8 cmd); //读取触摸平控制器X方向AD值
alt_u16 TS_Read_Y_Ad(alt_u8 cmd); //读取触摸平控制器Y方向AD值
void TS_Calibrate(void); //触摸屏校
void TSP_Test(void);
#endif //_TSP_H_