?? helio.c
字號:
/*** $Id: helio.c,v 1.17 2003/11/21 12:15:37 weiym Exp $**** helio.c: Low Level Input Engine for Helio Touch Panel** ** Copyright (C) 2000, Wei YongMing ** Copyright (C) 2000, BluePoint Software.**** Created by Wei YongMing, 2001/01/17*//*** 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*/#include <stdio.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include "common.h"#ifdef _HELIO_IAL#include <sys/ioctl.h>#include <sys/poll.h>#include "misc.h"#include "ial.h"#include "helio.h"static unsigned char state [NR_KEYS];static int tp_fd = -1;static int btn_fd;static char btn_state=0;static int tp_px=0, tp_py=0, tp_pz=0, tp_pb=0;static int enable_coor_transf = 1;#define TPH_DEV_FILE "/dev/tpanel"#define BTN_DEV_FILE "/dev/buttons"/* define if have helio buttons */#define _HELIO_BUTTONS 1#define _TP_HELIO 1#undef _TP_TSBREF#define TRANS_PER_PIXEL 4#define BUTTON_L 4#define DATACHANGELIMIT 50typedef struct{ /* * Coefficients for the transformation formulas: * * m = (ax + by + c) / s * n = (dx + ey + f) / s * * These formulas will transform a device point (x, y) to a * screen point (m, n) in fractional pixels. The fraction * is 1 / TRANS_PER_PIXEL. */ int a, b, c, d, e, f, s;} TRANSF_COEF; static TRANSF_COEF tc;static int GetPointerCalibrationData(void){ /* * Read the calibration data from the calibration file. * Calibration file format is seven coefficients separated by spaces. */ /* Get pointer calibration data from this file */ const char cal_filename[] = "/etc/pointercal"; int items; FILE* f = fopen(cal_filename, "r"); if ( f == NULL ) { /* now if we can't open /etc/pointercal, we should launch an application * to calibrate touch panel. so we should disable enable_coor_transf * so that the application could get raw data from touch panel */ enable_coor_transf = 0; return 0; } items = fscanf(f, "%d %d %d %d %d %d %d", &tc.a, &tc.b, &tc.c, &tc.d, &tc.e, &tc.f, &tc.s); if ( items != 7 ) { fprintf(stderr, "Improperly formatted pointer calibration file %s.\n", cal_filename); return -1; } return 0;}static POINT DeviceToScreen(POINT p){ /* * Transform device coordinates to screen coordinates. * Take a point p in device coordinates and return the corresponding * point in screen coodinates. * This can scale, translate, rotate and/or skew, based on the * coefficients calculated above based on the list of screen * vs. device coordinates. */ static POINT prev; /* set slop at 3/4 pixel */ const short slop = TRANS_PER_PIXEL * 3 / 4; POINT new, out; /* transform */ new.x = (tc.a * p.x + tc.b * p.y + tc.c) / tc.s; new.y = (tc.d * p.x + tc.e * p.y + tc.f) / tc.s; /* hysteresis (thanks to John Siau) */ if ( abs(new.x - prev.x) >= slop ) out.x = (new.x | 0x3) ^ 0x3; else out.x = prev.x; if ( abs(new.y - prev.y) >= slop ) out.y = (new.y | 0x3) ^ 0x3; else out.y = prev.y; prev = out; return out;}static int PD_Open(void){ /* * open up the touch-panel device. * Return the fd if successful, or negative if unsuccessful. */#ifndef _TP_HELIO struct scanparam s; int settle_upper_limit; int result;#endif tp_fd = open(TPH_DEV_FILE, O_RDONLY); if (tp_fd < 0) { fprintf(stderr, "Error %d opening touch panel\n", errno); return -1; }#ifdef _TP_TSBREF return tp_fd;#endif#ifndef _TP_HELIO /* set interval to 5000us (200Hz) */ s.interval = 1000; /* * Upper limit on settle time is approximately (scan_interval / 5) - 60 * (5 conversions and some fixed overhead) * The opmtimal value is the lowest that doesn't cause significant * distortion. * 50% of upper limit works well on my Clio. 25% gets into distortion. */ settle_upper_limit = (s.interval / 5) - 60; s.settletime = settle_upper_limit * 50 / 100; result = ioctl(tp_fd, TPSETSCANPARM, &s); if ( result < 0 ) fprintf(stderr, "Error %d, result %d setting scan parameters.\n", result, errno);#endif if (enable_coor_transf) { if (GetPointerCalibrationData() < 0) { close (tp_fd); return -1; } } return tp_fd;}static void PD_Close(void){ /* Close the touch panel device. */ if (tp_fd > 0) close(tp_fd); tp_fd = -1;}static int PD_Read(int *px, int *py, int *pz, int *pb){ /* * Read the tpanel state and position. * Returns the position data in x, y, and button data in b. * Returns -1 on error. * Returns 0 if no new data is available. * Returns 1 if position data is relative (i.e. mice). * Returns 2 if position data is absolute (i.e. touch panels). * Returns 3 if position data is not available, but button data is. * This routine does not block. * * Unlike a mouse, this driver returns absolute postions, not deltas. */ /* If z is below this value, ignore the data. */ /* const int low_z_limit = 900; EVEREX*/#ifndef _TP_HELIO const int low_z_limit = 815;#endif /* * I do some error masking by tossing out really wild data points. * Lower data_change_limit value means pointer get's "left behind" * more easily. Higher value means less errors caught. * The right setting of this value is just slightly higher than * the number of units traversed per sample during a "quick" stroke. */#ifndef _TP_HELIO const int data_change_limit = DATACHANGELIMIT;#endif static int have_last_data = 0; static int last_data_x = 0; static int last_data_y = 0; /* * Thanks to John Siau <jsiau@benchmarkmedia.com> for help with the * noise filter. I use an infinite impulse response low-pass filter * on the data to filter out high-frequency noise. Results look * better than a finite impulse response filter. * If I understand it right, the nice thing is that the noise now * acts as a dither signal that effectively increases the resolution * of the a/d converter by a few bits and drops the noise level by * about 10db. * Please don't quote me on those db numbers however. :-) * The end result is that the pointer goes from very fuzzy to much * more steady. Hysteresis really calms it down in the end (elsewhere). * * iir_shift_bits effectively sets the number of samples used by * the filter * (number of samples is 2^iir_shift_bits). * Lower iir_width means less pointer lag, higher iir_width means * steadier pointer. */#ifndef _TP_HELIO const int iir_shift_bits = 3; const int iir_sample_depth = (1 << iir_shift_bits);#endif static int iir_accum_x = 0; static int iir_accum_y = 0; static int iir_accum_z = 0; static int iir_count = 0; int data_x, data_y, data_z; /* read a data point */#ifdef _TP_HELIO short data[3];#else short data[6];#endif int bytes_read; bytes_read = read(tp_fd, data, sizeof(data)); if (bytes_read != sizeof(data)) { if (errno == EINTR || errno == EAGAIN) { return 0; } return -1; }#ifdef _TP_TSBREF if(data[0]&0x8000) { *px = data[2] - data[1]; *py = data[4] - data[3]; *pz = 0; *pb = BUTTON_L; return 2; }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -