📄 mc68328digi.c
字号:
/* * Write the SPIM (data and control). */#define SET_SPIMDATA(x) { SPIMDATA = x; }#define SET_SPIMCONT(x) { SPIMCONT = x; }/*----------------------------------------------------------------------------*/#define SPIM_ENABLE { SET_SPIMCONT(SPIMCONT_ENABLE); } /* enable SPIM */#define SPIM_INIT { SPIMCONT |= SPIMCONT_INIT; } /* init SPIM */#define SPIM_DISABLE { SET_SPIMCONT(0x0000); } /* disable SPIM *//*----------------------------------------------------------------------------*/#ifdef CONFIG_XCOPILOT_BUGS# define CARD_SELECT # define CARD_DESELECT #else# define CARD_SELECT { CS_DATA &= ~CS_MASK; } /* PB4 active (=low) */# define CARD_DESELECT { CS_DATA |= CS_MASK; } /* PB4 inactive (=high) */#endif/*----------------------------------------------------------------------------*/#define ENABLE_PEN_IRQ { IMR &= ~IMR_MPEN; }#define ENABLE_SPIM_IRQ { IMR &= ~IMR_MSPI; SPIMCONT |= SPIMCONT_IRQEN; }#define DISABLE_PEN_IRQ { IMR |= IMR_MPEN; }#define DISABLE_SPIM_IRQ { SPIMCONT &= ~SPIMCONT_IRQEN; IMR |= IMR_MSPI; }#define CLEAR_SPIM_IRQ { SPIMCONT &= ~SPIMCONT_IRQ; }/*----------------------------------------------------------------------------*//* predefinitions ------------------------------------------------------------*/static void handle_timeout(void);static void handle_pen_irq(int irq, void *dev_id, struct pt_regs *regs);static void handle_spi_irq(void);/*----------------------------------------------------------------------------*//* structure -----------------------------------------------------------------*/struct ts_pen_position { int x,y; };struct ts_queue { unsigned long head; unsigned long tail; wait_queue_head_t proc_list; struct fasync_struct *fasync; unsigned char buf[TS_BUF_SIZE];};/*----------------------------------------------------------------------------*//* Variables -----------------------------------------------------------------*//* * driver state variable. */static int ts_drv_state;/* * first tick initiated at ts_open. */static struct timeval first_tick;/* * pen state. */static int new_pen_state;/* * event counter. */static int ev_counter;/* * counter to differentiate a click from a move. */static int state_counter;static struct timer_list ts_wake_time;/* * drv parameters. */static struct ts_drv_params current_params;static int sample_ticks;/* * pen info variables. */static struct ts_pen_info ts_pen;static struct ts_pen_info ts_pen_prev;static struct ts_pen_position current_pos;/* * driver management. */static struct ts_queue *queue;static int device_open = 0; /* number of open device to prevent concurrent * access to the same device *//*----------------------------------------------------------------------------*//* Init & release functions --------------------------------------------------*/static void init_ts_state(void) { DISABLE_SPIM_IRQ; /* Disable SPIM interrupt */ ts_drv_state = TS_DRV_IDLE; state_counter = 0; ENABLE_PEN_IRQ; /* Enable interrupt IRQ5 */}static void init_ts_pen_values(void) { ts_pen.x = 0;ts_pen.y = 0; ts_pen.dx = 0;ts_pen.dy = 0; ts_pen.event = EV_PEN_UP; ts_pen.state &= 0;ts_pen.state |= ST_PEN_UP; ts_pen_prev.x = 0;ts_pen_prev.y = 0; ts_pen_prev.dx = 0;ts_pen_prev.dy = 0; ts_pen_prev.event = EV_PEN_UP; ts_pen_prev.state &= 0;ts_pen_prev.state |= ST_PEN_UP; new_pen_state = 0; ev_counter = 0; do_gettimeofday(&first_tick);}static void init_ts_timer(struct timer_list *timer) { init_timer(timer); timer->function = (void *)handle_timeout;}static void release_ts_timer(struct timer_list *timer) { del_timer(timer);}/* * Set default values for the params of the driver. */static void init_ts_settings(void) { current_params.version = MC68328DIGI_VERSION; current_params.version_req = 0; current_params.x_ratio_num = 1; current_params.x_ratio_den = 1; current_params.y_ratio_num = 1; current_params.y_ratio_den = 1; current_params.x_offset = 0; current_params.y_offset = 0; current_params.xy_swap = 1; current_params.x_min = 0; current_params.x_max = 4095; current_params.y_min = 0; current_params.y_max = 4095; current_params.mv_thrs = 50; current_params.follow_thrs = 5; /* to eliminate the conversion noise */ current_params.sample_ms = 20; current_params.deglitch_on = 1; //added by duwei 07/03/2003 current_params.deglitch_ms=1; current_params.event_queue_on = 1; sample_ticks = TICKS(current_params.sample_ms);}static void init_ts_hardware(void) { /* Set bit 2 of port F for interrupt (IRQ5 for pen_irq) */#if 0 PENIRQ_PUEN |= PEN_MASK; /* Port F as pull-up */#endif PENIRQ_DIR &= ~PEN_MASK; /* PF1 as input */ PENIRQ_SEL &= ~PEN_MASK; /* PF1 internal chip function is connected */#if 0 /* Set polarity of IRQ5 as low (interrupt occure when signal is low) */ ICR &= ~ICR_PENPOL;#endif /* Init stuff for port E. The 3 LSB are multiplexed with the SPIM */ PESEL &= ~PESEL_MASK; /* Set bit 4 of port B for the CARD_SELECT signal of ADS7843 as output. */#ifndef CONFIG_XCOPILOT_BUGS CS_PUEN |= CS_MASK; /* Port B as pull-up */ CS_DIR |= CS_MASK; /* PB4 as output */ CS_DATA |= CS_MASK; /* PB4 inactive (=high) */ CS_SEL |= CS_MASK; /* PB4 as I/O not dedicated */#endif /* Set bit 5 of port F for the BUSY signal of ADS7843 as input */ // PFPUEN |= BUSY_MASK; /* Port F as pull-up */ //PFDIR &= ~BUSY_MASK; /* PF5 as input */ // PFSEL |= BUSY_MASK; /* PF5 I/O port function pin is connected *///changed by duwei 03/21/2003 PBPUEN |= BUSY_MASK; /* Port F as pull-up */ PBDIR &= ~BUSY_MASK; /* PF5 as input */ PBSEL |= BUSY_MASK; /* PF5 I/O port function pin is connected */#ifdef USE_PENIRQ_PULLUP /* Set bit 4 of port D for the pen irq pull-up of ADS7843 as output. */ PDDIR |= PEN_MASK_2; /* PD4 as output */ PDDATA |= PEN_MASK_2; /* PD4 up (pull-up) */ PDPUEN |= PEN_MASK_2; /* PD4 as pull-up */#ifndef CONFIG_XCOPILOT_BUGS PDSEL |= PEN_MASK_2; /* PD4 I/O port function pin is connected */#endif#endif}/* * Reset bits used in each register to their default value. */static void release_ts_hardware(void) { /* Register default value */#ifndef CONFIG_XCOPILOT_BUGS PESEL |= PESEL_MASK; /* PESEL 0xFF */ CS_DIR &= ~CS_MASK; /* PBDIR 0x00 */ //CS_DIR |= CS_MASK; //changed by duwei 05/29/2003 CS_DATA &= ~CS_MASK; /* PBDATA 0x00 */ CS_PUEN |= CS_MASK; /* PBPUEN 0xFF */ CS_SEL |= CS_MASK; /* PBSEL 0xFF */#ifdef USE_PENIRQ_PULLUP PDDIR |= PEN_MASK_2; /* PDDIR 0xFF */ PDDATA |= PEN_MASK_2; /* PDDATA 0xF0 */ PDPUEN |= PEN_MASK_2; /* PDPUEN 0xFF */ PDSEL |= PEN_MASK_2; /* PDSEL 0xF0 */#endif PENIRQ_PUEN |= PEN_MASK; /* PFPUEN 0xFF */ PENIRQ_DIR &= ~PEN_MASK; /* PFDIR 0x00 */ PENIRQ_SEL |= PEN_MASK; /* PFSEL 0xFF */#endif IMR |= IMR_MPEN; /* IMR 0xFFFFFFFF */ /* I release it anyway! */ }static void init_ts_drv(void) { printk("a\n"); init_ts_state(); printk("b\n"); init_ts_pen_values(); printk("c\n"); init_ts_timer(&ts_wake_time); printk("d\n"); init_ts_hardware(); printk("e\n");}static void release_ts_drv(void) { release_ts_timer(&ts_wake_time); release_ts_hardware();}/*----------------------------------------------------------------------------*//* scaling functions ---------------------------------------------------------*/static inline void rescale_xpos(int *x) { *x &= CONV_MASK; *x *= current_params.x_ratio_num; *x /= current_params.x_ratio_den; *x += current_params.x_offset; *x = (*x > current_params.x_max ? current_params.x_max : (*x < current_params.x_min ? current_params.x_min : *x));}static inline void rescale_ypos(int *y) { *y &= CONV_MASK; *y *= current_params.y_ratio_num; *y /= current_params.y_ratio_den; *y += current_params.y_offset; *y = (*y > current_params.y_max ? current_params.y_max : (*y < current_params.y_min ? current_params.y_min : *y));}static inline void swap_xy(int *x, int *y){ if(current_params.xy_swap) { int t = *x; *x = *y; *y = t; }}/*----------------------------------------------------------------------------*//* xcopilot compatibility hacks ----------------------------------------------*/#ifdef CONFIG_XCOPILOT_BUGS/* xcopilot has the following bugs: * * - Disabling the penirq has no effect; we keep on getting irqs even when * penirq is disabled; this is not too annoying: we just trash pen irq events * that come when disabled. * * - SPIM interrupt is not simulated; this is not too annoying: we just read * SPI data immediately and bypass a couple of states related to SPI irq. * * - We do not get mouse drag events; this is a known xcopilot bug. * This is annoying: we miss all moves ! You should patch and recompile * your xcopilot. * * This has been reported as Debian bug #64367, and there is a patch there: * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=64367&repeatmerged=yes * which is: * +-----------------------------------------------------------------------+ * | --- display.c Tue Aug 25 14:56:02 1998 * | +++ display2.c Fri May 19 16:07:52 2000 * | @@ -439,7 +439,7 @@ * | static void HandleDigitizer(Widget w, XtPointer client_data, XEvent\ * | *event, Boolean *continue_to_dispatch) * | { * | - Time start; * | + static Time start; * | * | *continue_to_dispatch = True; * +-----------------------------------------------------------------------+ * In short, add 'static' to the declaration of 'start' in HandleDigitizer() * in display.c * * With this patch, all works perfectly ! * * - The pen state can be read only in IPR, not in port D; again, we're doing * the workaround. * * With all these workarounds in this file, and with the patch on xcopilot, * things go perfectly smoothly. * *//* * Ugly stuff to read the mouse position on xcopilot * * We get the position of the last mouse up/down only, we get no moves !!! :-( */static void xcopilot_read_now(void) { PFDATA &= ~0xf; PFDATA |= 6; SPIMCONT |= SPIMCONT_XCH | SPIMCONT_IRQEN; current_pos.x = SPIMDATA; rescale_xpos(¤t_pos.x); PFDATA &= ~0xf; PFDATA |= 9; SPIMCONT |= SPIMCONT_XCH | SPIMCONT_IRQEN; current_pos.y = SPIMDATA; rescale_ypos(¤t_pos.y); swap_xy(¤t_pos.x, ¤t_pos.y);}#endif/*----------------------------------------------------------------------------*//* flow functions ------------------------------------------------------------*//* * Set timer irq to now + delay ticks. */static void set_timer_irq(struct timer_list *timer,int delay) { del_timer(timer); timer->expires = jiffies + delay; add_timer(timer);}/* * Set ADS7843 and SPIM parameters for transfer. */static void set_SPIM_transfert(void) { /* DragonBall drive I/O 1 and I/O 2 LOW to reverse bias the PENIRQ diode * of the ADS7843 */#ifdef USE_PENIRQ_PULLUP PDDATA &= ~PEN_MASK_2; /* Pull down I/0 2 of PENIRQ */#endif PENIRQ_DIR |= PEN_MASK; /* I/O 1 of PENIRQ as output */ PENIRQ_DATA &= ~PEN_MASK; /* Pull down I/O 2 of PENIRQ */ /* Initiate selection and parameters for using the Burr-Brown ADS7843 * and the DragonBall SPIM. */ CARD_SELECT; /* Select ADS7843. */// printk("Now the ADS7843 is selected!\n"); SPIM_ENABLE; /* Enable SPIM */ SPIM_INIT; /* Set SPIM parameters */}/* * Clock the Burr-Brown to fall the AD_BUSY. * With a 'start' bit and PD1,PD0 = 00 to enable PENIRQ. * Used for the first pen irq after booting. And when error occures during * conversion that need an initialisation. */static void fall_BUSY_enable_PENIRQ(void) { SET_SPIMDATA(SPIMDATA_NOP); SPIMCONT |= SPIMCONT_XCH; /* initiate exchange */}/* * Release transfer settings. */static void release_SPIM_transfert(void) { SPIM_DISABLE; CARD_DESELECT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -