From: <sen...@us...> - 2009-02-28 22:22:52
|
Revision: 368 http://open2x.svn.sourceforge.net/open2x/?rev=368&view=rev Author: senquack Date: 2009-02-28 22:22:47 +0000 (Sat, 28 Feb 2009) Log Message: ----------- Added source code for touchscreen calibration utility Added Paths: ----------- trunk/utils/ts_calibrator/ trunk/utils/ts_calibrator/Makefile trunk/utils/ts_calibrator/SFont.c trunk/utils/ts_calibrator/SFont.h trunk/utils/ts_calibrator/img/ trunk/utils/ts_calibrator/img/bg.png trunk/utils/ts_calibrator/img/font_wh.png trunk/utils/ts_calibrator/img/target.png trunk/utils/ts_calibrator/ts_calibrator.c Added: trunk/utils/ts_calibrator/Makefile =================================================================== --- trunk/utils/ts_calibrator/Makefile (rev 0) +++ trunk/utils/ts_calibrator/Makefile 2009-02-28 22:22:47 UTC (rev 368) @@ -0,0 +1,33 @@ +CFLAGS=-c -O2 -g -Wall -DPLATFORM_GP2X -mcpu=arm920t -mtune=arm920 -ffast-math -W -Wall -pthread -msoft-float +LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib -Wl,-rpath,/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib -lSDL_gfx -lSDL_image -ljpeg -lpng12 -lz -lSDL -lpthread -lgcc -lm -lc -ldl -msoft-float -O2 + +SOURCES=SFont.c ts_calibrator.c + +OBJECTS=$(SOURCES:.c=.o) +EXECUTABLEGP=ts_calibrator + +CC=arm-open2x-linux-gcc +STRIP=arm-open2x-linux-strip +CFLAGS+=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include/ \ + -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/include/ \ + -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include/SDL -D_REENTRANT + +all: + make gpversion + +gpversion: $(SOURCES) $(EXECUTABLEGP) + + +$(EXECUTABLEGP): $(OBJECTS) + $(CC) $(OBJECTS) -o $@ $(LDFLAGS) + $(STRIP) $@ + +.c.o: + $(CC) $(CFLAGS) $< -o $@ + +cleanobjs: + rm -f $(OBJECTS) + +clean: + -rm -f ts_calibrator *~ *.o *.bak + Added: trunk/utils/ts_calibrator/SFont.c =================================================================== --- trunk/utils/ts_calibrator/SFont.c (rev 0) +++ trunk/utils/ts_calibrator/SFont.c 2009-02-28 22:22:47 UTC (rev 368) @@ -0,0 +1,182 @@ +/* SFont: a simple font-library that uses special .pngs as fonts + Copyright (C) 2003 Karl Bartel + + License: GPL or LGPL (at your choice) + WWW: http://www.linux-games.com/sfont/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Karl Bartel + Cecilienstr. 14 + 12307 Berlin + GERMANY + ka...@gm... +*/ +#include <SDL.h> + +#include <assert.h> +#include <stdlib.h> +#include "SFont.h" + +//DKS - added for memory debugging: +//#include "..\memwatch.h" + + +static Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y) +{ + Uint8 *bits; + Uint32 Bpp; + + assert(X>=0); + assert(X<Surface->w); + + Bpp = Surface->format->BytesPerPixel; + bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp; + + // Get the pixel + switch(Bpp) { + case 1: + return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X); + break; + case 2: + return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X); + break; + case 3: { // Format/endian independent + Uint8 r, g, b; + r = *((bits)+Surface->format->Rshift/8); + g = *((bits)+Surface->format->Gshift/8); + b = *((bits)+Surface->format->Bshift/8); + return SDL_MapRGB(Surface->format, r, g, b); + } + break; + case 4: + return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X); + break; + } + + return -1; +} + +SFont_Font* SFont_InitFont(SDL_Surface* Surface) +{ + int x = 0, i = 0; + Uint32 pixel; + SFont_Font* Font; + Uint32 pink; + + if (Surface == NULL) + return NULL; + + Font = (SFont_Font *) malloc(sizeof(SFont_Font)); + Font->Surface = Surface; + + SDL_LockSurface(Surface); + + pink = SDL_MapRGB(Surface->format, 255, 0, 255); + while (x < Surface->w) { + if (GetPixel(Surface, x, 0) == pink) { + Font->CharPos[i++]=x; + while((x < Surface->w) && (GetPixel(Surface, x, 0)== pink)) + x++; + Font->CharPos[i++]=x; + } + x++; + } + Font->MaxPos = x-1; + + pixel = GetPixel(Surface, 0, Surface->h-1); + SDL_UnlockSurface(Surface); + SDL_SetColorKey(Surface, SDL_SRCCOLORKEY, pixel); + + return Font; +} + +void SFont_FreeFont(SFont_Font* FontInfo) +{ + SDL_FreeSurface(FontInfo->Surface); + free(FontInfo); +} + +void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font, + int x, int y, const char *text) +{ + const char* c; + int charoffset; + SDL_Rect srcrect, dstrect; + + if(text == NULL) + return; + + // these values won't change in the loop + srcrect.y = 1; + dstrect.y = y; + srcrect.h = dstrect.h = Font->Surface->h - 1; + + for(c = text; *c != '\0' && x <= Surface->w ; c++) { + charoffset = ((int) (*c - 33)) * 2 + 1; + // skip spaces and nonprintable characters + if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) { + x += Font->CharPos[2]-Font->CharPos[1]; + continue; + } + + srcrect.w = dstrect.w = + (Font->CharPos[charoffset+2] + Font->CharPos[charoffset+1])/2 - + (Font->CharPos[charoffset] + Font->CharPos[charoffset-1])/2; + srcrect.x = (Font->CharPos[charoffset]+Font->CharPos[charoffset-1])/2; + dstrect.x = x - (float)(Font->CharPos[charoffset] + - Font->CharPos[charoffset-1])/2; + + SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect); + + x += Font->CharPos[charoffset+1] - Font->CharPos[charoffset]; + } +} + +int SFont_TextWidth(const SFont_Font *Font, const char *text) +{ + const char* c; + int charoffset=0; + int width = 0; + + if(text == NULL) + return 0; + + for(c = text; *c != '\0'; c++) { + charoffset = ((int) *c - 33) * 2 + 1; + // skip spaces and nonprintable characters + if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) { + width += Font->CharPos[2]-Font->CharPos[1]; + continue; + } + + width += Font->CharPos[charoffset+1] - Font->CharPos[charoffset]; + } + + return width; +} + +int SFont_TextHeight(const SFont_Font* Font) +{ + return Font->Surface->h - 1; +} + +void SFont_WriteCenter(SDL_Surface *Surface, const SFont_Font *Font, + int y, const char *text) +{ + SFont_Write(Surface, Font, Surface->w/2 - SFont_TextWidth(Font, text)/2, + y, text); +} + Added: trunk/utils/ts_calibrator/SFont.h =================================================================== --- trunk/utils/ts_calibrator/SFont.h (rev 0) +++ trunk/utils/ts_calibrator/SFont.h 2009-02-28 22:22:47 UTC (rev 368) @@ -0,0 +1,83 @@ +/* SFont: a simple font-library that uses special bitmaps as fonts + Copyright (C) 2003 Karl Bartel + + License: GPL or LGPL (at your choice) + WWW: http://www.linux-games.com/sfont/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Karl Bartel + Cecilienstr. 14 + 12307 Berlin + GERMANY + ka...@gm... +*/ + +/************************************************************************ +* SFONT - SDL Font Library by Karl Bartel <ka...@gm...> * +* * +* All functions are explained below. For further information, take a * +* look at the example files, the links at the SFont web site, or * +* contact me, if you problem isn' addressed anywhere. * +* * +************************************************************************/ +#ifndef SFONT_H +#define SFONT_H + +#include <SDL.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Delcare one variable of this type for each font you are using. +// To load the fonts, load the font image into YourFont->Surface +// and call InitFont( YourFont ); +typedef struct { + SDL_Surface *Surface; + int CharPos[512]; + int MaxPos; +} SFont_Font; + +// Initializes the font +// Font: this contains the suface with the font. +// The Surface must be loaded before calling this function +SFont_Font* SFont_InitFont (SDL_Surface *Font); + +// Frees the font +// Font: The font to free +// The font must be loaded before using this function. +void SFont_FreeFont(SFont_Font* Font); + +// Blits a string to a surface +// Destination: the suface you want to blit to +// text: a string containing the text you want to blit. +void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font, int x, int y, + const char *text); + +// Returns the width of "text" in pixels +int SFont_TextWidth(const SFont_Font* Font, const char *text); +// Returns the height of "text" in pixels (which is always equal to Font->Surface->h) +int SFont_TextHeight(const SFont_Font* Font); + +// Blits a string to Surface with centered x position +void SFont_WriteCenter(SDL_Surface *Surface, const SFont_Font* Font, int y, + const char *text); + +#ifdef __cplusplus +} +#endif + +#endif /* SFONT_H */ Added: trunk/utils/ts_calibrator/img/bg.png =================================================================== (Binary files differ) Property changes on: trunk/utils/ts_calibrator/img/bg.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/utils/ts_calibrator/img/font_wh.png =================================================================== (Binary files differ) Property changes on: trunk/utils/ts_calibrator/img/font_wh.png ___________________________________________________________________ Added: svn:executable + * Added: svn:mime-type + application/octet-stream Added: trunk/utils/ts_calibrator/img/target.png =================================================================== (Binary files differ) Property changes on: trunk/utils/ts_calibrator/img/target.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/utils/ts_calibrator/ts_calibrator.c =================================================================== --- trunk/utils/ts_calibrator/ts_calibrator.c (rev 0) +++ trunk/utils/ts_calibrator/ts_calibrator.c 2009-02-28 22:22:47 UTC (rev 368) @@ -0,0 +1,416 @@ +/* lcdadjuster.c LCD adjustment utility for Open2X. + Copyright (C) 2008 Dan Silsby (Senor Quack) + Portions of code based on : + + cpuctrl.c for GP2X (CPU/LCD/RAM-Tuner Version 2.0) + Copyright (C) 2006 god_at_hell + original CPU-Overclocker (c) by Hermes/PS2Reality + the gamma-routine was provided by theoddbot + parts (c) Rlyehs Work + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +//#include <linux/fb.h> +#include <unistd.h> +#include <stropts.h> +#include <errno.h> +#include <SDL.h> +#include <SDL_image.h> +#include <SDL_gfxPrimitives.h> +#include "SFont.h" + +#define GP2X_BUTTON_UP (0) +#define GP2X_BUTTON_DOWN (4) +#define GP2X_BUTTON_LEFT (2) +#define GP2X_BUTTON_RIGHT (6) +#define GP2X_BUTTON_UPLEFT (1) +#define GP2X_BUTTON_UPRIGHT (7) +#define GP2X_BUTTON_DOWNLEFT (3) +#define GP2X_BUTTON_DOWNRIGHT (5) +#define GP2X_BUTTON_CLICK (18) +#define GP2X_BUTTON_A (12) +#define GP2X_BUTTON_B (13) +#define GP2X_BUTTON_X (15) +#define GP2X_BUTTON_Y (14) +#define GP2X_BUTTON_L (11) +#define GP2X_BUTTON_R (10) +#define GP2X_BUTTON_START (8) +#define GP2X_BUTTON_SELECT (9) +#define GP2X_BUTTON_VOLUP (16) +#define GP2X_BUTTON_VOLDOWN (17) +#define NUMBUTTONS (19) // total number of buttons we'll need to keep track of + +#define MINPRESSURE (35000) // Any pressures below this are probably inaccurate +#define OFFSET 30 // Offset from edges of screen the readings are taken + +typedef struct { + unsigned short pressure; + unsigned short x; + unsigned short y; + unsigned short pad; +} ts_sample; + +extern int errno; + +char *settings_filename = "/etc/pointercal"; +int ts_dev; +ts_sample samples[2]; // We read two samples to calibrate + + +//global surfaces +SDL_Surface* screen; // framebuffer +SDL_Surface* background; +SDL_Surface* target; // image to show where to tap the stylus + +//global fonts +SFont_Font *font_wh; //white + +//global joysticks +SDL_Joystick* joy; + + +//global constants +const int screenw = 320; +const int screenh = 240; +const int screenbpp = 16; +const int screenflags = SDL_DOUBLEBUF; + + +// Return 1 on success, 0 on error. Write settings from timings structure. +int write_calvals(const char *filename, ts_sample *samples_read) +{ + FILE *handle; + char buf[100]; + int a, b, c, d, e, f, s, left, right, top, bottom; + + s = 1 << 16; + + left = samples_read->x; + top = samples_read->y; + + samples_read++; // advance to second sample in array + + right = samples_read->x; + bottom = samples_read->y; + + a = s * (OFFSET - (319 - OFFSET)) / (left - right); + b = 0; + c = s * OFFSET - a * left; + + d = 0; + e = s * (OFFSET - (239 - OFFSET)) / (top - bottom); + f = s * OFFSET - e * top; + + handle = fopen(filename, "w"); + if (handle == NULL) + { + printf("Error opening file for writing: %s\n", filename); + return 0; + } + else + { + printf("Writing new calibration values to file: %s\n", filename); + } + + sprintf(buf, "%d %d %d %d %d %d %d", a, b, c, d, e, f, s); + fprintf(handle, buf); + + return (fclose(handle) == 0); +} + + +int load_graphics(void) +{ + SDL_Surface *tmp_sur, *tmp_sur2; + + // Background image + tmp_sur = IMG_Load("img/bg.png"); + if (!tmp_sur) + { + fprintf(stderr, "Fatal error loading: img/bg.png\n"); + return 0; + } + background = SDL_DisplayFormat(tmp_sur); + SDL_FreeSurface(tmp_sur); + + // Target image + tmp_sur = IMG_Load("img/target.png"); + if (!tmp_sur) + { + fprintf(stderr, "Fatal error loading: img/target.png\n"); + return 0; + } + target = SDL_DisplayFormat(tmp_sur); + SDL_FreeSurface(tmp_sur); + SDL_SetColorKey(target, SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 255, 0, 255)); + + + //Font + tmp_sur = IMG_Load("img/font_wh.png"); + if (!tmp_sur) + { + fprintf ( stderr,"Fatal error loading: img/font_wh.png\n" ); + return 1; + } + tmp_sur2 = SDL_DisplayFormat(tmp_sur); + font_wh = SFont_InitFont(tmp_sur2); + if (!font_wh) + { + fprintf ( stderr,"Fatal error intializing SFont on font_wh.png\n" ); + return 1; + } + SDL_FreeSurface(tmp_sur); + + return 1; +} + +void unload_graphics(void) +{ + SDL_FreeSurface(background); + SDL_FreeSurface(target); + + if (font_wh) + { + SFont_FreeFont(font_wh); + } +} + +// Read a touchscreen sample. Return 1 if sample was read successfully, 0 if not. +int read_ts(int handle, ts_sample *sample) +{ + return(read(handle, sample, sizeof(ts_sample)) == sizeof(ts_sample)); +} + +// Returns 1 if user completed calibration or 0 if user requested to abort the calibration +int calibration_sequence(void) +{ + int quit = 0; + int times_pressed = 0; // how many times has the stylus been pressed? if 2, we're done + + SDL_Rect dstrect; + + const int line_y[4] = { 13, 23, 33, 43 }; // Four lines on which we can place text + + int i; + for (i = 0; i < 77; i+=4) + { + //blit background + SDL_BlitSurface(background, NULL, screen, NULL); + // animated menu border + rectangleRGBA(screen, ((screenw >> 1) - i), 1, ((screenw >> 1) + i), 58, + 255, 255, 255, 255); + dstrect.x = (screenw >> 1) - i + 1; + dstrect.y = 2; + dstrect.w = ((screenw >> 1) + i) - ((screenw >> 1) - i) - 2; + dstrect.h = 55; + SDL_FillRect(screen, &dstrect, SDL_MapRGB(screen->format, 50, 50, 50)); + SDL_Flip(screen); + } + + while (!quit) + { + // calibration loop + + //blit background + SDL_BlitSurface(background, NULL, screen, NULL); + + //blit menu border & BG + rectangleRGBA(screen, ((screenw >> 1) - 80), 1, ((screenw >> 1) + 80), 58, + 255, 255, 255, 255); + dstrect.x = (screenw >> 1) - 80 + 1; + dstrect.y = 2; + dstrect.w = ((screenw >> 1) + 80) - ((screenw >> 1) - 80) - 1; + dstrect.h = 56; + SDL_FillRect(screen, &dstrect, SDL_MapRGB(screen->format, 50, 50, 50)); + + SFont_WriteCenter(screen, font_wh, 0, "Open2X Touchscreen Calibration"); + + // draw menu text + SFont_WriteCenter(screen, font_wh, line_y[3], "Press any button to abort"); + + if (times_pressed == 0) + { + SFont_WriteCenter(screen, font_wh, line_y[1], "Tap stylus on target"); + // draw first target + dstrect.x = OFFSET - (target->w >> 1); + dstrect.y = OFFSET - (target->h >> 1); + dstrect.w = target->w; + dstrect.h = target->h; + SDL_BlitSurface(target, NULL, screen, &dstrect); + } + else if (times_pressed == 1) + { + SFont_WriteCenter(screen, font_wh, line_y[1], "Tap stylus on next target"); + // draw second target + dstrect.x = (319 - OFFSET) - (target->w >> 1); + dstrect.y = (239 - OFFSET) - (target->h >> 1); + dstrect.w = target->w; + dstrect.h = target->h; + SDL_BlitSurface(target, NULL, screen, &dstrect); + } + + ts_sample sample; + if (read_ts(ts_dev, &sample)) + { + // successfully read a sample + if (sample.pressure > MINPRESSURE) + { + samples[times_pressed] = sample; + times_pressed++; + // don't move on until stylus is released for a period of time + int stylus_still_pressed = 1; + while (stylus_still_pressed) + { + if (read_ts(ts_dev, &sample) && sample.pressure == 0) + { + stylus_still_pressed = 0; + } + SDL_Delay(20); + } + + if (times_pressed == 1) + { + // animate the target moving from one spot to another + const int num_steps = 100; + float x_incr = (float)(((319 - OFFSET) - (target->w >> 1)) - OFFSET) / + (float)num_steps; + float y_incr = (float)(((239 - OFFSET) - (target->h >> 1)) - OFFSET) / + (float)num_steps; + float dst_x = OFFSET - (target->w >> 1); + float dst_y = OFFSET - (target->h >> 1); + dstrect.w = target->w; + dstrect.h = target->h; + + for (i = 0; i < num_steps; i++) + { + dstrect.x = dst_x; + dstrect.y = dst_y; + SDL_BlitSurface(background, NULL, screen, NULL); + SDL_BlitSurface(target, NULL, screen, &dstrect); + SDL_Flip(screen); + dst_x += x_incr; + dst_y += y_incr; + } + } +// SDL_Delay(500); + } + } + + if (times_pressed == 2) + { + quit = 1; + } + + // update screen and wait a bit + SDL_Flip(screen); + SDL_Delay(10); + + SDL_JoystickUpdate(); + for (i = 0; i < NUMBUTTONS; i++) + { + if (SDL_JoystickGetButton(joy, i)) + { + quit = 1; + } + } + } + + return (times_pressed == 2); +} + +int initialize(void) +{ + if (!(screen = SDL_SetVideoMode(screenw, screenh, screenbpp, screenflags))) + { + fprintf(stderr, "cannot open %dx%d display: %s\n", + screenw, screenh, SDL_GetError()); + return 0; + } + + SDL_ShowCursor(SDL_DISABLE); + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { + fprintf(stderr, "Cannot initialize SDL system: %s\n", SDL_GetError()); + return 0; + } + + joy = SDL_JoystickOpen(0); + if (joy == NULL) + { + fprintf(stderr, "Cannot initialize GP2X joystick: %s\n", SDL_GetError()); + } + + if (!load_graphics()) { + fprintf(stderr, "Error loading sprites/fonts.\n"); + return 0; + } + + ts_dev = open("/dev/touchscreen/wm97xx",O_RDONLY|O_NDELAY); + if (ts_dev == -1) + { + fprintf(stderr, "Error opening touchscreen device.\n"); + return 0; + } + + return 1; +} + +void shutdown(void) +{ + close(ts_dev); + unload_graphics(); + SDL_Quit(); +} + +int main(int argc, char *argv[]) +{ + // Initialize graphics, load sprits/fonts etc, open touchscreen device + if (!initialize()) + { + fprintf(stderr, "Aborting because of initialization errors.\n"); + return 1; + } + + // RUN CALIBRATION + if (calibration_sequence()) + { + // Returned 1, user completed calibration + if (write_calvals(settings_filename, samples)) + { + printf("Successfully saved new values.\n"); + } + else + { + printf("Problem occurred writing new values.\n"); + } + + sync(); + } + else + { + // Returned 0, user aborted calibration sequence + printf("User aborted.\n"); + } + + shutdown(); + + return 0; +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |