⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vr4181.c

📁 miniucgui1.30版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** $Id: vr4181.c,v 1.15 2003/09/04 03:38:26 weiym Exp $**** vr4181.c: Low Level Input Engine for NEC VR4181 debug board.** ** Copyright (C) 2001 RedFlag Software. **** Author: Luo Gang.**** Created by Wei Yongming, 2001/08/20*//*** 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 <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <sys/poll.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <linux/kd.h>#include "common.h"#ifdef _VR4181_IAL#include "ial.h"#include "vr4181.h"/* define _VR_BUTTONS to include button handling */#undef _VR_BUTTONS#define TP_DEV_FILE  "/dev/tpanel"#define BTN_DEV_FILE "/dev/vrbuttons"#define WIDTH       320#define HEIGHT      240typedef struct {    short b;    short x;    short y;    short pad;} POS;typedef struct {    int a;    int b;    int c;    int d;    int e;    int f;    int s;} TRANSF_COEFF;typedef struct{        int x, y;} XYPOINT;struct scanparam {        unsigned int        interval;        unsigned int        settletime;};#define TPGETSCANPARM _IOR( 0xB0, 0x00, struct scanparam )#define TPSETSCANPARM _IOW( 0xB0, 0x01, struct scanparam )static int ts = -1;static int mousex = 0;static int mousey = 0;static int mousez = 0;static unsigned short btn_state = 0;static unsigned char state[NR_KEYS];#ifdef _VR_BUTTONSstatic int btn_fd = -1;#endif/* * Set default scan interval in microseconds (50 Hz). * If you adjust this value, you may also want to adust iir_shift_bits * in VrTpanelRead. */int scan_interval = 20000;/* * Set default settle time in microseconds. * Functional upper limit on settle time is approximately * (scan_interval / 5) - 60 (5 conversions and some fixed overhead * fitting within scan interval).  The opmtimal value is the lowest * that doesn't cause significant distortion.  The lower the value, * the more "simultaneous" and thus coherent the conversions. * 480us is probably a reasonable value for most hardware.  Lower * than that can get into distortion. */int scan_settle_time = 480;/* * Set default low z limit.  If z measurement data is below this value, * ignore the data. */int low_z_limit = 800;/* * Enable absolute coordinate transformation. * Normally this should be left at 1. * To disable transformation, set it to 0 before calling VrPanelInit. * This is done by the pointer calibration utility since it's used to produce the pointer * calibration data file. */int Vr_enable_transform = 1;#if TESTstatic int show_raw = 0;static int show_filtered = 0;static int show_enqueue = 0;#endifstatic TRANSF_COEFF tc;static int GetPointerCalibrationData(void){        /*         * Read the calibration data from the calibration file.         * Calibration file format are these values separated by spaces:         * - Seven tranformation coefficients a, b, c, d, e, f, and g         * - Scan interval microseconds         * - Scan settle time in microseconds         * - Low-z limit         */        /* Get pointer calibration data from this file */        const char cal_filename[] = "/etc/pointercal";        int items;        FILE* cf = fopen (cal_filename, "r");        if ( cf == NULL ) {                fprintf(stderr, "Error %d opening pointer calibration file %s.\n",                        errno, cal_filename);                return -1;        }        items = fscanf(cf, "%d %d %d %d %d %d %d %d %d %d",                &tc.a, &tc.b, &tc.c, &tc.d, &tc.e, &tc.f, &tc.s,                &scan_interval, &scan_settle_time, &low_z_limit);        if (items < 7) {                fprintf(stderr, "Improperly formatted pointer calibration file %s.\n",                        cal_filename);                fclose(cf);                return -1;        }        fclose(cf);        return 0;}#ifndef TRANSFORMATION_UNITS_PER_PIXEL#define TRANSFORMATION_UNITS_PER_PIXEL        4#endifXYPOINT DeviceToScreen(XYPOINT p){        /*         * Transform device coordinates to screen coordinates.         * Take a point p in device coordinates and return the corresponding         * point in fractional screen coodinates (fraction is         * 1 / TRANSFORMATION_UNITS_PER_PIXEL).         *         * It can scale, translate, rotate and/or skew, based on the coefficients         * calculated above based on the list of screen vs. device coordinates.         */        static XYPOINT prev;        /* Slop is how far the pointer has to move before we will allow the output         * to change.  Optimal is probably 3/4 of a pixel, but that might not be         * enough for some panels that are very noisey.         * Using larger values appears to makes the pointer movement more "blocky".         * This is noticeable, say,  when drawing a line at a 45 degree angle.         */        /* TODO: make this configurable */        const short slop = TRANSFORMATION_UNITS_PER_PIXEL * 3 / 4;        XYPOINT 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 VrTpanelInit(void){     /*     * Open up the touch-panel device.     * Return the fd if successful, or negative if unsuccessful.     */    struct scanparam s;    int result;    int fd;    /* Read the calibration file first for scan interval and settling time. */    GetPointerCalibrationData();    /* Open the touch-panel device. */    fd = open (TP_DEV_FILE, O_RDONLY);    if (fd < 0) {        fprintf(stderr, "Error %d opening touch panel\n", errno);        return -1;    }    s.interval = scan_interval;    s.settletime = scan_settle_time;    result = ioctl (fd, TPSETSCANPARM, &s);    if ( result < 0 )        fprintf(stderr, "Error %d, result %d setting scan parameters.\n", result, errno);    return fd;}/* mouse button bits in BUTTON */#define  LBUTTON        04#define  MBUTTON        02#define  RBUTTON        01static int VrTpanelRead(int fd, int *px, int *py, int *pz, unsigned int *pb){        /*         * This driver returns absolute postions, not deltas.         * Returns the position in px, py, pressure in pz, and buttons pb.         * Returns -1 on error.         * Returns 0 if no new data is available.         * Does not return 1 (which is for relative position data).         * 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.         */        /*         * 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.         * I figure a fast pen scribble can cover about 3000 pixels in one second on a typical screen.         * There are typically about 3 to 6 points of touch-panel resolution per pixel.         * So 3000 pixels-per-second * 3 to 6 tp-points-per-pixel / 50 samples-per-second =         * 180 to 360 tp points per scan.         */        /* TODO: make this configurable */        const int data_change_limit = 360;        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).         *         * Setting iir_shift_bits lower allows shorter "taps" and less pointer lag, but a         * fuzzier pointer, which can be especially bad for display update when dragging.         *         * Setting iir_shift_bits higher requires longer "presses" and causes more pointer lag,         * but it provides steadier pointer.         *         * If you adjust iir_shift_bits, you may also want to adjust the sample interval         * in VrTpanelInit.          *         * The filter gain is fixed at 8 times the input (gives room for increased resolution         * potentially added by the noise-dithering).         *         * The filter won't start outputing data until iir_count is above iir_output_threshold.         */        const int iir_shift_bits = 2;        const int iir_sample_depth = (1 << iir_shift_bits);        const int iir_output_threshold = 1;        const int iir_gain = 8;        static int iir_accum_x = 0;        static int iir_accum_y = 0;        static int iir_accum_z = 0;        static int iir_count = 0;        int iir_out_x;        int iir_out_y;        int iir_out_z;        int data_x, data_y, data_z;        /* read a data point */        short data[6];        int bytes_read;again:        bytes_read = read (fd, data, sizeof(data));        if (bytes_read != sizeof (data)) {                if (errno == EINTR)                        goto again;                else                        return -1;        }        /* did we lose any data? */        if ( (data[0] & 0x2000) )                fprintf(stderr, "Lost touch panel data\n");#if TEST        if ( show_raw )                printf("Raw %.4hx %s %s  x %5hd %5hd %5hd  y %5hd %5hd %5hd  z %5hd\n",                        data[0],                        data[0] & 0x8000 ? "data   " : "no data",                        data[0] & 0x4000 ? "down" : "up  ",                        data[1], data[2], data[2] - data[1],                        data[3], data[4], data[4] - data[3],                        data[5]);#endif        /* do we only have contact state data (no position data)? */        if ( (data[0] & 0x8000) == 0 ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -