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

📄 mc68328digi.c

📁 老外写的触摸屏驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef USE_PENIRQ_PULLUP  PDDATA |= PEN_MASK_2;       /* Pull up I/0 2 of PENIRQ   */#endif  PENIRQ_DIR  &= ~PEN_MASK;   /* I/O 1 of PENIRQ as input  */  PENIRQ_DATA |= PEN_MASK;    /* Pull down I/O 2 of PENIRQ */}/* * Ask for an X conversion. */static void ask_x_conv(void) {  SET_SPIMDATA(SPIMDATA_ASKX);  SPIMCONT |= SPIMCONT_XCH;     /* initiate exchange */}/* * Ask for an Y conversion. */static void ask_y_conv(void) {  SET_SPIMDATA(SPIMDATA_ASKY);  SPIMCONT |= SPIMCONT_XCH;     /* initiate exchange */}/* * Get the X conversion. Re-enable the PENIRQ. */static void read_x_conv(void) {  current_pos.x = (SPIMDATA & 0x7FF8) >> 3;  /*   * The first clock is used to fall the BUSY line and the following 15 clks   * to transfert the 12 bits of the conversion, MSB first.   * The result will then be in the SPIM register in the bits 14 to 3.   */  SET_SPIMDATA(SPIMDATA_NOP);   /* nop with a start bit to re-enable */  SPIMCONT |= SPIMCONT_XCH;     /* the pen irq.                      */  rescale_xpos(&current_pos.x);}/* * Get the Y result. Clock the Burr-Brown to fall the BUSY. */static void read_y_conv(void) {  current_pos.y = (SPIMDATA & 0x7FF8) >> 3;  /* Same remark as upper. */  SET_SPIMDATA(SPIMDATA_NULL);  /* No start bit to fall the BUSY without */  SPIMCONT |= SPIMCONT_XCH;     /* initiating another BUSY...            */  rescale_ypos(&current_pos.y);}/* * Get one char from the queue buffer. * AND the head with 'TS_BUF_SIZE -1' to have the loopback */static unsigned char get_char_from_queue(void) {  unsigned int result;  result = queue->buf[queue->tail];  queue->tail = (queue->tail + 1) & (TS_BUF_SIZE - 1);  return result;}/* * Write one event in the queue buffer. * Test if there is place for an event = the head cannot be just one event * length after the queue. */static void put_in_queue(char *in, int len) {  unsigned long head    = queue->head;  unsigned long maxhead = (queue->tail - len) & (TS_BUF_SIZE - 1);  int i;    if(head != maxhead)              /* There is place for the event */    for(i=0;i<len;i++) {      queue->buf[head] = in[i];      head++;      head &= (TS_BUF_SIZE - 1);    }  //else printk("%0: Queue is full !!!!\n", __file__);  queue->head = head;}/* * Test if queue is empty. */static inline int queue_empty(void) {  return queue->head == queue->tail;}/* * Test if the delta move of the pen is enough big to say that this is a really * move and not due to noise. */static int is_moving(void) {  int threshold;  int dx, dy;    threshold=((ts_pen_prev.event & EV_PEN_MOVE) > 0 ?             current_params.follow_thrs : current_params.mv_thrs);  dx = current_pos.x-ts_pen_prev.x;  dy = current_pos.y-ts_pen_prev.y;  if(dx < 0) dx = -dx; /* abs() */  if(dy < 0) dy = -dy;  return (dx > threshold ? 1 :	  (dy > threshold ? 1 : 0));}static void copy_info(void) {  ts_pen_prev.x = ts_pen.x;  ts_pen_prev.y = ts_pen.y;  ts_pen_prev.dx = ts_pen.dx;  ts_pen_prev.dy = ts_pen.dy;  ts_pen_prev.event = ts_pen.event;  ts_pen_prev.state = ts_pen.state;  ts_pen_prev.ev_no = ts_pen.ev_no;  ts_pen_prev.ev_time = ts_pen.ev_time;}unsigned long set_ev_time(void) {  struct timeval now;  do_gettimeofday(&now);  return (now.tv_sec -first_tick.tv_sec )*1000 +         (now.tv_usec-first_tick.tv_usec)/1000;}static void cause_event(int conv) {  switch(conv) {  case CONV_ERROR: /* error occure during conversion */    ts_pen.state &= 0;            /* clear */    ts_pen.state |= ST_PEN_UP;    /* recover a stable state for the drv.      */    ts_pen.state |= ST_PEN_ERROR; /* tell that the state is due to an error   */    ts_pen.event = EV_PEN_UP;     /* event = pen go to up */    ts_pen.x = ts_pen_prev.x;     /* get previous coord as current to by-pass */    ts_pen.y = ts_pen_prev.y;     /* possible errors                          */    ts_pen.dx = 0;    ts_pen.dy = 0;    ts_pen.ev_no = ev_counter++;    /* get no of event   */    ts_pen.ev_time = set_ev_time(); /* get time of event */    copy_info();                    /* remember info */    if(current_params.event_queue_on)      put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */    /* tell user space progs that a new state occure */    new_pen_state = 1;    /* signal asynchronous readers that data arrives */    if(queue->fasync)      kill_fasync(&queue->fasync, SIGIO, POLL_IN);    wake_up_interruptible(&queue->proc_list);  /* tell user space progs */    break;      case CONV_LOOP:  /* pen is down, conversion continue */        ts_pen.state &= 0;          /* clear */    ts_pen.state &= ST_PEN_DOWN;    switch(state_counter) {       /* It could be a move   */	        case 1:    /* the pen just went down, it's a new state */      ts_pen.x = current_pos.x;      ts_pen.y = current_pos.y;      ts_pen.dx = 0;      ts_pen.dy = 0;      ts_pen.event = EV_PEN_DOWN;      /* event = pen go to down */      ts_pen.ev_no = ev_counter++;     /* get no of event        */      ts_pen.ev_time = set_ev_time();  /* get time of event */      copy_info();                     /* remember info */      if(current_params.event_queue_on)        put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */      /* tell user space progs that a new state occure */      new_pen_state = 1;      /* signal asynchronous readers that data arrives */      if(queue->fasync)        kill_fasync(&queue->fasync, SIGIO, POLL_IN);      wake_up_interruptible(&queue->proc_list);  /* tell user space progs */      break;    case 2:    /* the pen is down for at least 2 loop of the state machine */      if(is_moving()) {        ts_pen.event = EV_PEN_MOVE;        ts_pen.x = current_pos.x;        ts_pen.y = current_pos.y;        ts_pen.dx = ts_pen.x - ts_pen_prev.x;        ts_pen.dy = ts_pen.y - ts_pen_prev.y;        ts_pen.ev_no = ev_counter++;    /* get no of event   */        ts_pen.ev_time = set_ev_time(); /* get time of event */        copy_info();                    /* remember info */        if(current_params.event_queue_on)          put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */        /*	 * pen is moving, then it's anyway a good reason to tell it to	 * user space progs	 */        new_pen_state = 1;        /* signal asynchronous readers that data arrives */        if(queue->fasync)          kill_fasync(&queue->fasync, SIGIO, POLL_IN);        wake_up_interruptible(&queue->proc_list);      }      else {        if(ts_pen_prev.event == EV_PEN_MOVE)  /* if previous state was moving */	  ts_pen.event = EV_PEN_MOVE;         /* -> keep it!                  */        ts_pen.x = ts_pen_prev.x;       /* No coord passing to     */        ts_pen.y = ts_pen_prev.y;       /* avoid Parkinson effects */        ts_pen.dx = 0;	ts_pen.dy = 0;  /* no wake-up interruptible because nothing new */        copy_info();    /* remember info */      }      break;    }    break;  case CONV_END:   /* pen is up, conversion ends */    ts_pen.state &= 0;         /* clear */    ts_pen.state |= ST_PEN_UP;    ts_pen.event = EV_PEN_UP;    ts_pen.x = current_pos.x;    ts_pen.y = current_pos.y;    ts_pen.dx = ts_pen.x - ts_pen_prev.x;    ts_pen.dy = ts_pen.y - ts_pen_prev.y;    ts_pen.ev_time = set_ev_time();  /* get time of event */    ts_pen.ev_no = ev_counter++;     /* get no of event   */    copy_info();                     /* remember info */    if(current_params.event_queue_on)      put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */    /* tell user space progs that a new state occure */    new_pen_state = 1;    /* signal asynchronous readers that data arrives */    if(queue->fasync)      kill_fasync(&queue->fasync, SIGIO, POLL_IN);    wake_up_interruptible(&queue->proc_list);    break;  }}/*----------------------------------------------------------------------------*//* Interrupt functions -------------------------------------------------------*//* * pen irq. */static void handle_pen_irq(int irq, void *dev_id, struct pt_regs *regs) {  unsigned long flags;  int bypass_initial_timer = 0;  /* if unwanted interrupts come, trash them */   if(!device_open)    return;  PENIRQ_DATA &= ~PEN_MASK;#ifdef CONFIG_XCOPILOT_BUGS  if(IMR&IMR_MPEN) {    return;  }#endif  save_flags(flags);     /* disable interrupts */  cli();  switch(ts_drv_state) {  case TS_DRV_IDLE:      DISABLE_PEN_IRQ;    ts_drv_state++;      /* update driver state */    if(current_params.deglitch_on)   // if(current_params.deglitch_ms)   //changed by duwei at 07/02/2003      set_timer_irq(&ts_wake_time,sample_ticks);    else      bypass_initial_timer = 1;    break;  default: /* Error */    /* PENIRQ is enable then just init the driver      * Its not necessary to pull down the busy signal     */    init_ts_state();    break;  }      restore_flags(flags);  /* Enable interrupts */  /* if deglitching is off, we haven't started the deglitching timeout   * so we do the inital sampling immediately:   */  if(bypass_initial_timer)    handle_timeout();}/* * timer irq. */static void handle_timeout(void) {  unsigned long flags;  /* if unwanted interrupts come, trash them */   if(!device_open)    return;    save_flags(flags);     /* disable interrupts */  cli();    switch(ts_drv_state) {  case TS_DRV_IDLE:  /* Error in the idle state of the driver */    printk("%s: Error in the idle state of the driver\n", __file__);    goto treat_error;  case TS_DRV_ASKX:  /* Error in release SPIM   */    printk("%s: Error in release SPIM\n", __file__);    goto treat_error;  case TS_DRV_ASKY:  /* Error in ask Y coord    */    printk("%s: Error in ask Y coord\n", __file__);    goto treat_error;  case TS_DRV_READX: /* Error in read X coord   */    printk("%s: Error in read X coord\n", __file__);    goto treat_error;  case TS_DRV_READY: /* Error in read Y coord   */    printk("%s: Error in read Y coord\n", __file__);    goto treat_error;  treat_error:    /* Force re-enable of PENIRQ because of an abnormal termination. Limit this     * initialization with a timer to define a more FATAL error ...     */    set_timer_irq(&ts_wake_time,TICKS(CONV_TIME_LIMIT));    ts_drv_state = TS_DRV_ERROR;    CLEAR_SPIM_IRQ;              /* Consume residual irq from spim */    ENABLE_SPIM_IRQ;    fall_BUSY_enable_PENIRQ();    break;      case TS_DRV_WAIT:    if(state_counter) {      cause_event(CONV_LOOP);  /* only after one loop */    }    if(IS_PEN_DOWN) {      if(state_counter < 2) state_counter++;      set_timer_irq(&ts_wake_time,TICKS(CONV_TIME_LIMIT));      set_SPIM_transfert();      ts_drv_state++;      CLEAR_SPIM_IRQ;            /* Consume residual irq from spim */      ENABLE_SPIM_IRQ;      fall_BUSY_enable_PENIRQ();    }    else {      if(state_counter) {#ifdef CONFIG_XCOPILOT_BUGS	/* on xcopilot, we read the last mouse position now, because we	 * missed the moves, during which the position should have been	 * read	 */	xcopilot_read_now();#endif	cause_event(CONV_END);      }      init_ts_state();    }    break;      case TS_DRV_ERROR:  /* Busy doesn't want to fall down -> reboot? */    panic(__FILE__": cannot fall pull BUSY signal\n");  default:    init_ts_state();  }  restore_flags(flags);  /* Enable interrupts */#ifdef CONFIG_XCOPILOT_BUGS  if (ts_drv_state==TS_DRV_ASKX) {    handle_spi_irq();  }  PENIRQ_DATA |= PEN_MASK;#endif}/* * spi irq. */static void handle_spi_irq(void) {  unsigned long flags;  /* if unwanted interrupts come, trash them */   if(!device_open)    return;    save_flags(flags);     /* disable interrupts */  cli();    CLEAR_SPIM_IRQ;       /* clear source of interrupt */  switch(ts_drv_state) {  case TS_DRV_ASKX:#ifdef CONFIG_XCOPILOT_BUGS    /* for xcopilot we bypass all SPI interrupt-related stuff     * and read the pos immediately     */    xcopilot_read_now();    ts_drv_state = TS_DRV_WAIT;    DISABLE_SPIM_IRQ;    release_SPIM_transfert();    set_timer_irq(&ts_wake_time,sample_ticks);    break;

⌨️ 快捷键说明

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