// gcc -o activboard activboard.c -L/usr/X11R6/lib -lX11 -lXext -lXtst -lm /* * Copyright (C) 2007 Miguel Freitas * * This 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 software 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 * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define INPUT_MOTION (ExposureMask | ButtonPressMask | KeyPressMask | \ ButtonMotionMask | StructureNotifyMask | \ PropertyChangeMask | PointerMotionMask) #define LINE_LENGTH 30 #define DISTANCE_FROM_BORDER 100 #define DIST2(x1,y1,x2,y2) ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) #define DIST2_NEW_CLICK (4000*4000) #ifndef O_BINARY #define O_BINARY 0 #endif Display *display; Window window; Window child_win; Window root; int wx, wy; int screen; GC gc; double c[8]; static int SerialFd = -1; #define BAUDRATE B9600 int readActiveBoard(int *button, int *x, int *y) { unsigned char buf[10]; if( read( SerialFd, buf, 1 ) ) { if( buf[0] != 0x89 ) return 0; } else return 0; if( read( SerialFd, buf, 1 ) ) { if( buf[0] != 0x01 ) return 0; } else return 0; if( read( SerialFd, buf, 1 ) ) { if( buf[0] != 0x21 ) return 0; } else return 0; if( read( SerialFd, buf, 6 ) == 6 ) { if( buf[0] == 0x64 ) *button = 1; else if( buf[0] == 0x68 ) *button = 3; else *button = 0; *x = (buf[1] << 8) + buf[2]; *y = (buf[4] << 8) + buf[5]; return 1; } else return 0; } // see lu.c below int NUM_lu(double *matrix, double *solution, int neq); int calibrate(void) { int width; int height; int blackColor; int whiteColor; XWindowAttributes xattr; int i; width = DisplayWidth(display, screen); height = DisplayHeight(display, screen); blackColor = BlackPixel(display, screen); whiteColor = WhitePixel(display, screen); window = XCreateSimpleWindow(display, root, 0, 0, width, height, 1, whiteColor, whiteColor); XSelectInput (display, window, INPUT_MOTION); XMapRaised(display, window); XSync(display, False); for(;;) { XEvent e; XNextEvent(display, &e); if (e.type == MapNotify) break; } XGetWindowAttributes(display, window, &xattr); width = xattr.width; height = xattr.height; gc = XCreateGC(display, window, 0, NULL); XTranslateCoordinates(display, window, root, 0, 0, &wx, &wy, &child_win); { int lx[4] = {DISTANCE_FROM_BORDER, DISTANCE_FROM_BORDER, width-DISTANCE_FROM_BORDER, width-DISTANCE_FROM_BORDER}; int ly[4] = {DISTANCE_FROM_BORDER, height-DISTANCE_FROM_BORDER, DISTANCE_FROM_BORDER, height-DISTANCE_FROM_BORDER}; int boardx[4]; int boardy[4]; double A[4*(4+1)], Atmp[4*(4+1)]; int button; int lastx = 0, lasty = 0; for(i = 0; i < 4; i++) { XSetForeground(display, gc, blackColor); XDrawLine(display, window, gc, lx[i] - LINE_LENGTH/2, ly[i], lx[i] + LINE_LENGTH/2, ly[i]); XDrawLine(display, window, gc, lx[i], ly[i] - LINE_LENGTH/2, lx[i], ly[i] + LINE_LENGTH/2); XFlush(display); while(1) { if( readActiveBoard(&button, &boardx[i], &boardy[i]) && button ) { if( lastx && lasty ) { if( DIST2(lastx,lasty,boardx[i],boardy[i]) > DIST2_NEW_CLICK ) break; } else break; } } lastx = boardx[i]; lasty = boardy[i]; /* boardx[i] = lx[i]; boardy[i] = ly[i]; */ XSetForeground(display, gc, whiteColor); XDrawLine(display, window, gc, lx[i] - LINE_LENGTH/2, ly[i], lx[i] + LINE_LENGTH/2, ly[i]); XDrawLine(display, window, gc, lx[i], ly[i] - LINE_LENGTH/2, lx[i], ly[i] + LINE_LENGTH/2); XFlush(display); } for( i = 0; i < 4; i++ ) A[0+i] = (double) boardx[i]; for( i = 0; i < 4; i++ ) A[4+i] = (double) boardy[i]; for( i = 0; i < 4; i++ ) A[8+i] = (double) boardx[i] * boardy[i]; for( i = 0; i < 4; i++ ) A[12+i] = 1.0; memcpy(Atmp, A, sizeof(A)); for( i = 0; i < 4; i++ ) Atmp[16+i] = (double) lx[i] + wx; NUM_lu(Atmp, &c[0], 4); memcpy(Atmp, A, sizeof(A)); for( i = 0; i < 4; i++ ) Atmp[16+i] = (double) ly[i] + wy; NUM_lu(Atmp, &c[4], 4); } XDestroyWindow(display, window); XSync(display, False); for( i = 0; i < 8; i++ ) printf("%lf ", c[i]); printf("\n"); } int main(int argc, char *argv[]) { int event_base; int error_base; int major_version = 0; int minor_version = 0; int lastbutton; display = XOpenDisplay(NULL); root = DefaultRootWindow(display); screen = DefaultScreen(display); if( XTestQueryExtension(display, &event_base, &error_base, &major_version, &minor_version) != True ) { printf("XTest unsupported!\n"); return -1; } XSync(display, True); if( argc == 1 ) { printf("%s \n", argv[0]); return -1; } else { struct termios tio; SerialFd = open(argv[1], O_RDWR | O_NOCTTY ); if (SerialFd <0) { printf ("Erro abrindo porta serial (%s)!\n", argv[1]); return 1; } memset(&tio, 0, sizeof(tio)); tio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD | CRTSCTS; tio.c_iflag = IGNBRK; tio.c_oflag = 0; tio.c_lflag = 0; tio.c_cc[VTIME] = 10; /* inter-character timer *0.1s */ tio.c_cc[VMIN] = 0; /* blocking read until n chars received */ tcsetattr(SerialFd,TCSANOW,&tio); calibrate(); lastbutton = 0; while(1) { int x, y; double sx, sy; int button; if( readActiveBoard(&button, &x, &y) ) { sx = c[0] * x + c[1] * y + c[2] * x * y + c[3]; sy = c[4] * x + c[5] * y + c[6] * x * y + c[7]; XTestFakeMotionEvent(display, -1, (int)sx, (int)sy, CurrentTime); XSync(display, 0); printf("%d x:%05d y:%05d sx:%d sy:%d\r", button, x, y, (int)sx, (int)sy); fflush(stdout); if( button != lastbutton ) { if( button ) { XTestFakeButtonEvent(display, button, True, CurrentTime); XSync(display, 0); } else { XTestFakeButtonEvent(display, lastbutton, False, CurrentTime); XSync(display, 0); } } lastbutton = button; } } } return 0; } /* lu.c - PA = LU factorisation with pivoting * $Id: lu.c,v 1.4 2001/02/22 19:47:37 antoine Exp $ * Copyright (C) 2000 * Antoine Lefebvre * * * Licensed under the GPLv2 */ #include #include #include /* This algorithm will compute an LU factorisation on the augmented matrix (A) passed in arguments. This algorithm assumed the element on the diagonal of the lower triangular matrix set to 1. In order to save memory space, every coefficient of both matrix L and U are written in the original matrix overwriting initial values of A. */ int NUM_lu(double *matrix, double *solution, int neq) { int i, j, k; int idx; /* index of the larger pivot */ double big; /* the larger pivot found */ double tmp = 0.0; int *P; /* keep memory of permutation (column permutation) */ double *y; P = (int *) calloc (neq, sizeof(int)); y = (double *) calloc (neq, sizeof(double)); for (i = 0; i < neq; i++) { solution[i] = 0; /* reset the solution vector */ P[i] = i; /* initialize permutation vector */ } /* LU Factorisation */ for (i = 0; i < neq - 1; i++) /* line */ { for (j = i; j < neq; j++) /* column */ { tmp = 0.0; for (k = 0; k < i; k++) tmp += matrix[i + neq*P[k]] * matrix[k + neq*P[j]]; matrix[i + neq*P[j]] = matrix[i + neq*P[j]] - tmp; } /* find the larger pivot and interchange the columns */ big = 0.0; idx = i; for (j = i; j < neq; j++) { if (big < fabs(matrix[i + neq*P[j]])) /* we found a larger pivot */ { idx = j; big = fabs(matrix[i + neq*P[j]]); } } /* check if we have to interchange the lines */ if (idx != i) { tmp = P[i]; P[i] = P[idx]; P[idx] = tmp; } if (matrix[i + neq*P[i]] == 0.0) { printf("LU: matrix is singular, no unique solution.\n"); return -1; } for (j = i+1; j < neq; j++) { tmp = 0.0; for (k = 0; k < i; k++) tmp += matrix[j + neq*P[k]] * matrix[k + neq*P[i]]; matrix[j + neq*P[i]] = (matrix[j + neq*P[i]] - tmp)/matrix[i + neq*P[i]]; } } i = neq - 1; tmp = 0.0; for (k = 0; k < neq-1; k++) tmp += matrix[i + neq*P[k]] * matrix[k + neq*P[i]]; matrix[i + neq*P[i]] = matrix[i + neq*P[i]] - tmp; /* End LU-Factorisation */ /* substitution for y Ly = b*/ for (i = 0; i < neq; i++) { tmp = 0.0; for (j = 0; j < i; j++) tmp += matrix[i + neq*P[j]] * y[j]; y[i] = matrix[i + neq*neq] - tmp; } /* substitution for x Ux = y*/ for (i = neq - 1; i >=0; i--) { if (matrix[i + neq*P[i]] == 0.0) { printf("LU: No unique solution exist.\n"); return -1; } tmp = 0.0; for (j = i; j < neq; j++) tmp += matrix[i + neq*P[j]] * solution[P[j]]; solution[P[i]] = (y[i] - tmp)/matrix[i + neq*P[i]]; } free (y); free (P); return 0; }