画十字架, 原点x,y
x-10 y
x 10 y
x y 10
x y 10
void fb_disp_cross(int x, int y, unsigned int color)
{
draw_line(x-10, y, x 10, y, color);
draw_line(x, y-10, x, y 10, color);
}
编辑touchscreen.c
// 坐标的x值
static int g_ts_x;
// 坐标Y值
static int g_ts_y;
//表示数据并未有效
//设置成volatile类型,有两个地方会用到一个是中断report_ts_xy
//另一个是程序ts_read_raw,我们一定确保这个值是从内存中读取出来
//让双方得到真实的值
static volatile char g_ts_data_valid = 0;
void Isr_Adc(void)
{
int x = ADCDAT0;
int y = ADCDAT1;
if (!(x & (1<<15))) /* 如果仍然按下才打印 */
{
x &= 0x3ff;
y &= 0x3ff;
//我们现在不能打印
//printf("x = d, y = d\n\r", x, y);
//实现report_ts_xy函数来打印
report_ts_xy(x, y);
/* 启动定时器以再次读取数据 */
ts_timer_enable();
}
else
{
ts_timer_disable();
enter_wait_pen_down_mode();
}
enter_wait_pen_up_mode();
}
//report_ts_xy函数的实现
void report_ts_xy(int x, int y)
{
//printf("x = d, y = d\n\r", x, y);
//一开始标记位=0表示没有数据
if (g_ts_data_valid == 0)
{
g_ts_x = x;
g_ts_y = y;
g_ts_data_valid = 1;
}
}
//读到原始数据
void ts_read_raw(int *px, int *py)
{
//当按下触摸屏时会产生ADC中断
while (g_ts_data_valid == 0);
*px = g_ts_x;
*py = g_ts_y;
//读完数据清零
g_ts_data_valid = 0;
}
下面我们实现ts_calibrate校准函数,在tslib.c文件中
//设置斜率为全局变量
static double g_kx;
static double g_ky;
static int g_ts_xc, g_ts_yc;
static int g_lcd_xc, g_lcd_yc;
//加一个调换的全局变量
static int g_ts_xy_swap = 0;
/*
----------------------------
| |
| (A) (B) |
| |
| |
| |
| (E) |
| |
| |
| |
| (D) (C) |
| |
----------------------------
*/
把ABCDE这5个点都实现
void ts_calibrate(void)
{
unsigned int fb_base;
int xres, yres, bpp;
//定义ABCDE触摸屏坐标
int a_ts_x, a_ts_y;
int b_ts_x, b_ts_y;
int c_ts_x, c_ts_y;
int d_ts_x, d_ts_y;
int e_ts_x, e_ts_y;
/* X轴方向 */
int ts_s1, ts_s2;
int lcd_s;
/* Y轴方向 */
int ts_d1, ts_d2;
int lcd_d;
//通过调用framebuffer.c里面的函数,来获取LCD坐标
/* 获得LCD的参数: fb_base, xres, yres, bpp */
get_lcd_params(&fb_base, &xres, &yres, &bpp);
/* 对于ABCDE, 循环: 显示" "、点击、读ts原始值 */
//A坐标,X分辨率50, Y分辨率50
/* A(50, 50) */
get_calibrate_point_data(50, 50, &a_ts_x, &a_ts_y);
//B坐标,X分辨率-50
/* B(xres-50, 50) */
get_calibrate_point_data(xres-50, 50, &b_ts_x, &b_ts_y);
//C坐标,X分辨率-50,Y分辨率-50
/* C(xres-50, yres-50) */
get_calibrate_point_data(xres-50, yres-50, &c_ts_x, &c_ts_y);
//D坐标,X分辨率位置50,Y分辨率-50
/* D(50, yres-50) */
get_calibrate_point_data(50, yres-50, &d_ts_x, &d_ts_y);
//E坐标,X分辨率除2,Y分辨率除2
/* E(xres/2, yres/2) */
get_calibrate_point_data(xres/2, yres/2, &e_ts_x, &e_ts_y);
//读取XY坐标值后确定XY是否反转
/* 确定触摸屏数据XY是否反转 */
g_ts_xy_swap = is_ts_xy_swap(a_ts_x, a_ts_y, b_ts_x, b_ts_y);
//如果反转,对调所有点的XY坐标
if (g_ts_xy_swap)
{
/* 对调所有点的XY坐标 */
swap_xy(&a_ts_x, &a_ts_y);
swap_xy(&b_ts_x, &b_ts_y);
swap_xy(&c_ts_x, &c_ts_y);
swap_xy(&d_ts_x, &d_ts_y);
swap_xy(&e_ts_x, &e_ts_y);
}
/* 确定公式的参数并保存 */
//Ts_S1值=B点ts和A点tsX轴方向的距离
ts_s1 = b_ts_x - a_ts_x;
//Ts_S2值
ts_s2 = c_ts_x - d_ts_x;
//lcd_s值
lcd_s = xres-50 - 50;
//ts_d1值
ts_d1 = d_ts_y - a_ts_y;
//ts_d2值
ts_d2 = c_ts_y - b_ts_y;
//lcd_d值
lcd_d = yres-50-50;
//X轴的斜率
g_kx = ((double)(2*lcd_s)) / (ts_s1 ts_s2);
//Y轴的斜率
g_ky = ((double)(2*lcd_d)) / (ts_d1 ts_d2);
//中心点E点的坐标
g_ts_xc = e_ts_x;
g_ts_yc = e_ts_y;
g_lcd_xc = xres/2;
g_lcd_yc = yres/2;
}
我们需要把 在LCD上显示出来并且读出数据
void get_calibrate_point_data(int lcd_x, int lcd_y, int *px, int *py)
{
fb_disp_cross(lcd_x, lcd_y, 0xffffff);
/* 等待点击 */
ts_read_raw(px, py);
}
//比如我们之前发现上报的X轴Y轴值反了
//比如正常情况下从A点移动到B点是x值变化比较大y值不变,但是目前的情况是y值变化比较大,x值不变
//我分根据这个特性分辨
int is_ts_xy_swap(int a_ts_x, int a_ts_y, int b_ts_x, int b_ts_y)
{
int dx = b_ts_x - a_ts_x;
int dy = b_ts_y - a_ts_y;
//减出来的值有可能是负数,我们需要取绝对值
if (dx < 0)
dx = 0 - dx;
if (dy < 0)
dy = 0 - dy;
if(dx > dy)
return 0; /* xy没有反转 */
else
return 1; /* xy反了 */
}
//如果是反的我们需要调换回来,我们需要确定XY是否反转
//我们写出一个对调函数
void swap_xy(int *px, int *py)
{
int tmp = *px;
*px = *py;
*py = tmp;
}
/*
* 读TS原始数据, 转换为LCD坐标
*/
void ts_read(int *lcd_x, int *lcd_y)
{
int ts_x, ts_y;
ts_read_raw(&ts_x, ts_y);
if (g_ts_xy_swap)
{
swap_xy(&ts_x, &ts_y);
}
/* 使用公式计算 */
//斜率 * (触摸屏坐标 - 中心点除,触摸屏坐标) 中心点LCD坐标
*lcd_x = g_kx * (ts_x - g_ts_xc) g_lcd_xc;
*lcd_y = g_ky * (ts_y - g_ts_yc) g_lcd_yc;
}
接下来我们画线, 我们在framebuffer.c中把清屏函数单独实现
void clear_screen(unsigned int color)
{
int x, y;
unsigned char *p0;
unsigned short *p;
unsigned int *p2;
/* 往framebuffer中写数据 */
if (bpp == 8)
{
/* bpp: palette[color] */
p0 = (unsigned char *)fb_base;
for (x = 0; x < xres; x )
for (y = 0; y < yres; y )
*p0 = color;
}
else if (bpp == 16)
{
/* 让LCD输出整屏的红色 */
/* 565: 0xf700 */
p = (unsigned short *)fb_base;
for (x = 0; x < xres; x )
for (y = 0; y < yres; y )
*p = convert32bppto16bpp(color);
}
else if (bpp == 32)
{
p2 = (unsigned int *)fb_base;
for (x = 0; x < xres; x )
for (y = 0; y < yres; y )
*p2 = color;
}
}
先显示一个一个点,然后显示开始校准提示, 校准完提示 ok draw
打开我们的 touchscreen_test.c文件
void touchscreen_test(void)
{
unsigned int fb_base;
int xres, yres, bpp;
int x, y;
/* 获得LCD的参数: fb_base, xres, yres, bpp */
get_lcd_params(&fb_base, &xres, &yres, &bpp);
touchscreen_init();
/* 清屏 */
clear_screen(0);
//我们在70像素的地方显示文字,背景白色显示文字
/* 显示文字提示较准 */
fb_print_string(70, 70, "Touc cross to calibrate touchscreen", 0xffffff);
ts_calibrate();
/* 显示文字提示绘画 */
fb_print_string(70, yres - 70, "OK! To draw!", 0xffffff);
while (1)
{
ts_read(&x, &y);
//我们先打印值
printf(" x = %d, y = %d\n\r", x, y);
//描绿色的线
fb_put_pixel(x, y, 0xff00);
}
}
我们添加了 tslib.c需要修改Makefile
添加objs = adc_touchscreen/tslib.o
objs = start.o init.o nand_flash.o led.o uart.o main.o exception.o interrupt.o timer.o nor_flash.o my_printf.o string_utils.o lib1funcs.o
objs = lcd/font.o
objs = lcd/framebuffer.o
objs = lcd/geometry.o
objs = lcd/lcd.o
objs = lcd/lcd_4.3.o
objs = lcd/lcd_controller.o
objs = lcd/lcd_test.o
objs = lcd/s3c2440_lcd_controller.o
objs = lcd/font_8x16.o
objs = adc_touchscreen/adc.o
objs = adc_touchscreen/adc_test.o
objs = adc_touchscreen/touchscreen.o
objs = adc_touchscreen/touchscreen_test.o
objs = adc_touchscreen/tslib.o
all: $(objs)
#arm-linux-ld -Ttext 0 -Tdata 0x30000000 start.o led.o uart.o init.o main.o -o sdram.elf
arm-linux-ld -T sdram.lds $^ libgcc.a -o sdram.elf
arm-linux-objcopy -O binary -S sdram.elf sdram.bin
arm-linux-objdump -D sdram.elf > sdram.dis
clean:
rm -f *.bin $(objs) *.elf *.dis
%.o : %.c
arm-linux-gcc -march=armv4 -c -o $@ $<
%.o : %.S
arm-linux-gcc -march=armv4 -c -o $@ $<
,