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

📄 mypad.c

📁 一个MP3的键盘驱动程序,可以是按键式的也可以是转轮式的
💻 C
字号:
#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");

⌨️ 快捷键说明

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