?? mypad.c
字號(hào):
#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <asm/irq.h>#include <linux/delay.h>#include <asm/hardware.h>#define DEVICE_NAME "pad" //device name #define BUTTON_MAJOR 233 //major number#define DE GPIO_G11 //irq#define STB GPIO_E13 //clock#define SDATA GPIO_E12 //data,lsb#define IN 0#define OUT 1static struct key_info { int irq_no; unsigned int gpio_port; unsigned int mod;} key_info_tab[3] = { { IRQ_EINT19, DE , IN },//irq { IRQ_EINT19, STB , OUT },//clock { IRQ_EINT19, SDATA ,IN }//data,lsb};/******************* about ALT *********************/#define SIF1_MODE 0 // Definition of Serial Communication Mode#define SIF2_MODE 1// the value of OUTPUT_ENABLE and OUTPUT_THRESHOLD depends on your design.// if you need high speed or fast reaction, use small number. (the smallest is 1, means not using DCA)// On the contrary, if you need stability, use fairly big number (the biggest depends on how fast your MCU can acces ATA2501)#define OUTPUT_ENABLE 2// 5 // to receive this amount of sensor inputs to process DCA#define OUTPUT_THRESHOLD 1// 4 // Each sensor input must be greater than or equal to this value as HIGH (touched)#define SCROLL_TYPE 0 // Pad Design selection (0: scroll, 1: button)#define BUTTON_TYPE 1#define LINEAR_SCROLL 0 // Scroll type selection#define CIRCULAR_SCROLL 1 #define BOOL unsigned short#define BYTE unsigned char#define FALSE 0#define TRUE 1#define QUITE 3 //if need not DEBUG message,you can set the QUIT = 5#define NOISE 4#define PAD_DEBUG_VERBOSE NOISE#define DEBUG2(n, args...) \ if (n <= PAD_DEBUG_VERBOSE) { \ printk(args); \ }//--------------------------------------------------------------------------------------------------------------------// Prototypes//--------------------------------------------------------------------------------------------------------------------static void Init_G_Var( void ); // Initialize global variablesstatic void SIF_Read( unsigned int *sensDataIn ); // ATA2501 SIF communication function (SIF1, SIF2)static BOOL DCA(unsigned char numSensor, unsigned int sDataIn, unsigned int *sDataOut); // Selects the strongest inputsstatic char Button_Process( int numBtn, unsigned int dcaData ); // Choose one button among the strongest inputsstatic char Linear_Scroll_Process( int numScr, unsigned int dcaData, unsigned char *padPos ); // Calculates the movement of linear scrollstatic char Circular_Scroll_Process( int numScr, unsigned int scrData, unsigned char *padPos ); // Calculates the movement of circular scroll//--------------------------------------------------------------------------------------------------------------------// global variable definitions //--------------------------------------------------------------------------------------------------------------------unsigned char xPadPos; // save current pad position before fetching new sensor dataint outEnCount; // accumulates times of sensor data fetchunsigned char thCountReg[12]; // stores strength of each sensor padBOOL sifMode; // indicates current sif modeunsigned char padType; // indicates pad type (0: scroll type, 1: button type)BOOL scrType; // indicates scroll type (0: Linear type, 1: Circular Type)//--------------------------------------------------------------------------------------------------------------------// Code starts here//--------------------------------------------------------------------------------------------------------------------static void Init_G_Var( void ){ int i; xPadPos = 0xff; outEnCount = 0; for(i=0; i<12; i++) { thCountReg[i] = 0; } sifMode = SIF1_MODE; padType = BUTTON_TYPE; scrType = LINEAR_SCROLL;}static void send_a_clock(void){ struct key_info *k; k = key_info_tab + 1; //STB write_gpio_bit(k->gpio_port,1); //make STB bit to high udelay(10); write_gpio_bit(k->gpio_port,0); //mkae STB bit to low udelay(10); }static void SIF_Read( unsigned int *sensDataIn ){ unsigned char i; unsigned int dataTemp; unsigned int sensorIn = 0; unsigned int dataEnable; struct key_info *k; k = key_info_tab + 2;// sdata if( sifMode == SIF1_MODE ) { send_a_clock(); for( i=0; i<12; i++ ) { send_a_clock(); dataTemp = read_gpio_bit(k->gpio_port); // catch serial data from SDADA pin of DCC sensorIn |= dataTemp << i; } *sensDataIn = sensorIn; // DEBUG2(QUITE,"in SIF_Read :the sensorIn is %d\n",sensorIn); } else if( sifMode == SIF2_MODE ) { for( i=0; i<12; i++ ) { send_a_clock(); dataTemp = read_gpio_bit(k->gpio_port); // catch serial data from SDADA pin of DCC sensorIn |= dataTemp << i; } *sensDataIn = sensorIn; }}static BOOL DCA(BYTE numSensor, unsigned int sDataIn, unsigned int *sDataOut){/////////////////////////////////////////////////////////////////////////////////////////// int i; int maxCount = 0; //------------------------------------------------------- // update each pad counter for output threshold check //------------------------------------------------------- for( i=0; i<numSensor; i++ ) { if(( sDataIn >> i ) & 1 ) thCountReg[i]++; } //---------------------------------- // increment outEnCount //---------------------------------- outEnCount += 1; if( outEnCount != OUTPUT_ENABLE ) return( FALSE ); // select the biggest count among Pads *sDataOut = 0; for( i=0; i<numSensor; i++ ) { if( maxCount < thCountReg[i] ) { maxCount = thCountReg[i]; } } if( maxCount >= OUTPUT_THRESHOLD ) { for( i=0; i<numSensor; i++ ) { if( thCountReg[i] == maxCount ) { *sDataOut = *sDataOut | (1 << i); } } } // clear all thCount for( i=0; i<numSensor; i++ ) { thCountReg[i] = 0; } // clear outEnCount outEnCount = 0; return( TRUE );}static char Button_Process( int numBtn, unsigned int dcaData ){ int i; int count = 0; char checkPos; unsigned char position; for( i=0; i<numBtn; i++ ) { if( dcaData & (1<<i) ) count++; } if( count ) { if( xPadPos != 0xff ) { checkPos = dcaData & ( 1<<xPadPos ); if( checkPos ) { return( xPadPos ); } } for( i=0; i<numBtn; i++ ) { if( dcaData & ( 1<<i )) { position = i; break; } } } // end of if( count ); else { position = 0xff; } return( position );}static char Linear_Scroll_Process( int numScr, unsigned int scrData, unsigned char *padPos ){ int i; int count = 0; char dMove; *padPos = 0xff; for( i=0; i<numScr; i++ ) { if( scrData&(1<<i) ) *padPos = i; } if( *padPos == 0xff ) return( 0 ); if( xPadPos == 0xff ) return( 0 ); dMove = (char)(*padPos - xPadPos); switch( dMove ) { case -11: case -10: case -9: case -8: case -7: case -6: case -5: dMove = 0; break; case -4: case -3: case -2: dMove = -1; break; case -1: case 0: case 1: break; case 2: case 3: case 4: dMove = 1; break; case 5: case 6: case 7: case 8: case 9: case 10: case 11: dMove = 0; break; default: dMove = 0; break; } return( dMove );}static char Circular_Scroll_Process( int numScr, unsigned int scrData, unsigned char *padPos ){ int i; int count = 0; char dMove; *padPos = 0xff; for( i=0; i<numScr; i++ ) { if( scrData&(1<<i) ) *padPos = i; } if( *padPos == 0xff ) return( 0 ); if( xPadPos == 0xff ) return( 0 ); dMove = (char)(*padPos - xPadPos);/* delta = 0,1,2,3 OK delta = 4,5,6,7,8 Discard delta = 9,10,11 --> -3,-2,-1 delta = -1,-2,-3 OK delta = -4,-5,-6,-7,-8 Discard delta = -9,-10,-11 --> 3,2,1*/ switch( dMove ) { case -11: case -10: case -9: dMove = 1; break; case -8: case -7: case -6: case -5: case -4: dMove = 0; break; case -3: case -2: dMove = -1; break; case -1: case 0: case 1: break; case 2: case 3: dMove = 1; break; case 4: case 5: case 6: case 7: case 8: dMove = 0; break; case 9: case 10: case 11: dMove = -1; break; default: dMove = 0; break; } return( dMove );}/************************* about ALT end *****************************/static int ready = 0;static int key_value = 0;static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);//lxy:set gpio mode,in or out,according to the info in the key_info_tabstatic void gpio_init(void){ struct key_info *k; unsigned i; for (i = 1; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) //xiabiaocong 1 kaishi?? { k = key_info_tab + i; if (k->mod == IN) { //set_gpio_mode_user(k->gpio_port, GPIO_MODE_IN); what's this? set_gpio_ctrl(GPIO_MODE_IN | k->gpio_port); } else { //set_gpio_mode_user(k->gpio_port, GPIO_MODE_OUT); set_gpio_ctrl(GPIO_MODE_OUT | k->gpio_port); } }}static void buttons_irq(int irq, void *dev_id, struct pt_regs *reg){ unsigned int sensData, dcaData; unsigned char padPos; char delta; int i; int flags; save_flags(flags); cli(); //DEBUG2(QUITE," in buttons_irq!\n"); SIF_Read( &sensData ); // read 12 sensor data periodically if( DCA( 12, sensData, &dcaData )) // get the strongest inputs { if( padType == BUTTON_TYPE ) { padPos = Button_Process( 12, dcaData ); // choose one button among the strongest inputs // send padPos to main processor xPadPos = padPos; // update pad position } else if( padType == SCROLL_TYPE ) { if( scrType == LINEAR_SCROLL ) { delta = Linear_Scroll_Process( 12, dcaData, &padPos ); // calculate the movement } else if( scrType == CIRCULAR_SCROLL ) { delta = Circular_Scroll_Process( 12, dcaData, &padPos ); // calculate the movement } // send delta to main processor xPadPos = padPos; // update pad position } key_value = xPadPos; ready = 1; //get a powerfull data wake_up_interruptible(&buttons_wait); //wake up the wait quenu } for(i=0;i<100;i++) udelay(1); // delay about 1msec restore_flags(flags); sti();//lxy:unnecessary?} static int request_irqs(void){ struct key_info *k; k = key_info_tab ; set_external_irq(k->irq_no, EXT_RISING_EDGE, GPIO_PULLUP_DIS); //set the irq mode if (request_irq(k->irq_no, &buttons_irq, SA_INTERRUPT, DEVICE_NAME, &buttons_irq)) //request the irq { return -1; } return 0;}static void free_irqs(void){ struct key_info *k; k = key_info_tab ; free_irq(k->irq_no, buttons_irq);}static int pad_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos){ static int key; int flags; int repeat; if (!ready) return -EAGAIN; if (count != sizeof key_value) return -EINVAL; save_flags(flags); //disable local irq?? if (key != key_value) { key = key_value; repeat = 0; } else { repeat = 1; } restore_flags(flags); //enable local irq if (repeat) { //dispatch the repeat data ,if you want to get the data continuous ,you should add "//" before the line. return -EAGAIN; } copy_to_user(buffer, &key, sizeof key); ready = 0; return sizeof key_value;}static unsigned int pad_buttons_select( struct file *file, struct poll_table_struct *wait){ if (ready) return 1; poll_wait(file, &buttons_wait, wait); // add the current process to the wait quenu return 0;}static int pad_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ switch(cmd) { default: return -EINVAL; }}static struct file_operations pad_buttons_fops = { owner: THIS_MODULE, ioctl: pad_buttons_ioctl, poll: pad_buttons_select, read: pad_buttons_read,};static devfs_handle_t devfs_handle;static int __init pad_buttons_init(void){ int ret; unsigned int sensData1; ready = 0; ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &pad_buttons_fops); if (ret < 0) { printk(DEVICE_NAME " can't register major number\n"); return ret; } gpio_init(); //init the gpio drictions Init_G_Var(); //init the global varibales ret = request_irqs(); //request the irq if (ret) { unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME); printk(DEVICE_NAME " can't request irqs\n"); return ret; } devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,BUTTON_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &pad_buttons_fops, NULL); //added the device node?? return 0;}static void __exit pad_buttons_exit(void){ devfs_unregister(devfs_handle); free_irqs(); unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);}module_init(pad_buttons_init);module_exit(pad_buttons_exit);MODULE_LICENSE("GPL");
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -