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

📄 key_driver.c

📁 UART FOR uCOS and Capsensor Test
💻 C
字号:
/**
 * key driver for usdk130
 * liwei@actions, 2006,08
 *
 * Base on keydriver by houjingkun@actions for lsdk130
 *
 * module discription:
 *
 * there are mainly two funs inthis module:
 * 1. the key press_down ISR function, buttons_irq()
 * 2. the key release_up ISR function, whether_button_up()

 * NOTICE:
 * in the near future, we may add semaphores for key messgage buffer
 */
 /*
 *	V1.1 For touch key of EKT8120
 *	Modified by Richard, 2006,12
 */
#include "key_buf_queue.h"
#include "key_driver.h"
#include "irq.h"
#include "Atj213x.h"
#include "elf.h"
#include "drv_manager.h"
#include "includes.h"
#include "WM_Inc.h"
#include "task_key.h"

//#define DEBUG_INFO
#define UART2_INTERRUPT_NUM 19
#define UART2_CTL_ADDR		0xB0160020
#define UART2_RXDAT_ADDR	(UART2_CTL_ADDR + 0x4)
#define UART2_TXDAT_ADDR	(UART2_CTL_ADDR + 0x8)
#define UART2_STAT_ADDR		(UART2_CTL_ADDR + 0xc)

#define UART1_CTL_ADDR		0xB0160000
#define UART1_RXDAT_ADDR	(UART1_CTL_ADDR + 0x4)
#define UART1_TXDAT_ADDR	(UART1_CTL_ADDR + 0x8)
#define UART1_STAT_ADDR		(UART1_CTL_ADDR + 0xc)


//#define CMU_COREPLL			0xB0010000
//#define CMU_BUSCLK			(CMU_COREPLL + 0xc)
//#define CMU_UART1CLK		(CMU_COREPLL + 0x28)
//#define CMU_UART2CLK		(CMU_COREPLL + 0x2c)

static void init_button_reg(void);
static void whether_button_up(void);
static void init_timer_interrupt(void);   
static INT32S matrix8_buttons_init(void);
static INT32S matrix8_buttons_release();
static  int  translateKeyMessage(WM_KEY_INFO *keyInfo);


/**
forward declaration for hold status detecting
*/
void detect_hold_status(void);
void set_bool_holdkey_pressed(void);
void clear_bool_holdkey_pressed(void);
unsigned int is_bool_holdkey_pressed(void);






/*10*18 = 180ms*/
#define TICKS_KEY_DOWN_UP  18 /*INTERVAL between down and up*/

extern INT32U _dstart,_dend;
unsigned int keyapitbl[]={
	(unsigned int)matrix8_buttons_read,
	(unsigned int)is_bool_holdkey_pressed,
	(unsigned int)translateKeyMessage
};

addrInfo addr_info __addrdata=
							{
							startAddr: (INT32U)&_dstart,
							endAddr: (INT32U)&_dend
							};/*start/end addr of the drv*/

static drv_Info drvinfo = {
				"drv",
				matrix8_buttons_init,
				matrix8_buttons_release,
				(INT32U)keyapitbl
				};/*drvinfo required for installing drv*/						

extern INT32U key_value[KEY_MESSAGE_BUF_SIZE];
extern unsigned int spos;
extern unsigned int rpos;
/*this two static vars are used to save the value read from the key hardware IOs
* 
*/
static INT32U cur_key;
static INT32U save_key;
static INT32U irq_keyValue;

/*the soft timer for key up*/
static INT8U  KEY_UP_TIMER;  
static INT8U  SET_UARTCLK_TIMER;  
static unsigned int bool_holdkey_pressed = 0;

static unsigned int tp_reset_packet[4] = {0x54, 0xd8, 0x0, 0x1};
static unsigned int tp_synchronous_packet[4] = {0x00, 0x00, 0x00, 0x00};
static unsigned int tp_reset_flag;

void inline act_set_uart2_clk(void)
{
	unsigned int tmp;
	
	tmp = (act_readl(CMU_COREPLL) & 0x3f) * 6  / (((act_readl(CMU_BUSCLK) >> 2) & 0x3) + 1) * 1000000;
	tmp = tmp / (9600 * 8) - 1;
	
	if (tmp == (act_readl(CMU_UART2CLK) & 0xffff)) //if equal, no need to change
		return;
	
	act_writel(tmp | 0x10000, CMU_UART2CLK);
	mdelay(80);
}

void tp_send_reset(void)
{
	int i;
	act_writel(0xff, UART2_STAT_ADDR);
	for (i = 0; i<4 ; i++)
		act_writel(tp_reset_packet[i], UART2_TXDAT_ADDR);
}

void tp_send_synchronous(void)
{
	int i;
	act_writel(0xff, UART2_STAT_ADDR);
	for (i = 0; i<4 ; i++)
		act_writel(tp_synchronous_packet[i], UART2_TXDAT_ADDR);
}

void init_button_reg(void)
{
	INT32U tmp;
	tmp = act_readl(DEV_CLK_EN);
	tmp |= 0x06400000;	//Enable GPIO, key , Uart clk
	act_writel(tmp, DEV_CLK_EN);
	
	act_set_uart2_clk();		
	
	act_writel(act_readl(MULTI_CON1) | 0x80000110, MULTI_CON1);
	
	act_writel(0x0, UART2_STAT_ADDR);
	act_writel(act_readl(UART2_CTL_ADDR) | 0x48003, UART2_CTL_ADDR);
	act_writel(0xff, UART2_STAT_ADDR);
	
	#ifdef DEBUG_INFO
	printf("\nCMU_COREPLL = %x\n", act_readl(CMU_COREPLL));
	printf("\nCMU_BUSCLK = %x\n", act_readl(CMU_BUSCLK));
	printf("\nCMU_UART1CLK = %x\n", act_readl(CMU_UART1CLK));
	printf("\nCMU_UART2CLK = %x\n", act_readl(CMU_UART2CLK));
	printf("\nUART1_CTL_ADDR = %x\n", act_readl(UART1_CTL_ADDR));
	printf("\nUART2_CTL_ADDR = %x\n", act_readl(UART2_CTL_ADDR));
	#endif
	
}



 /*this func is the ISR for the release_timer
*  in this func, we save a new key release_up message by adding a bit in the 
* key press_down message in the key_message buffer
*/
void whether_button_up(void)
{
int ind;
unsigned int keyCon;


	/*init the key up timer( it is periodical ) at a very large value, 
	* so that it will not happen until there are a key down irq when the init cnt
	* value is modified. */
	mod_timer(KEY_UP_TIMER, 0xffffffff);

	if (irq_keyValue == 0)  {
			return;  
	}
	
	if ( is_full()) {	
//		printf("key buff full!!\n");
		qretrieve();
		return;
	}
	
	qstore(cur_key | 0x8000);
	
	save_key = 0;
	irq_keyValue = 0;

	return;
}

void set_uart_clk(void)
{
	act_set_uart2_clk();
}

/*  should be called by init  */
void init_timer_interrupt(void)   
{	
	timer_arg_t arg;
	arg.timerHandler = (void *) whether_button_up;
	arg.timerValue = 0xffffffff;
	arg.type = TIMER_CYCLE;
	
	KEY_UP_TIMER = set_timer(&arg);//INITIAL VALUE 

/**
Auto-set uart clk
*/
/*
	arg.timerHandler = (void *) set_uart_clk;
	arg.timerValue = 100;
	arg.type = TIMER_CYCLE;
	SET_UARTCLK_TIMER= set_timer(&arg);//INITIAL VALUE	
*/
}


static void buttons_irq(unsigned int irq, void *dev_id)
{
	INT32U keyCon;
	
#ifdef DEBUG_INFO
	//printf("\n into buttons_irq()  level 0 \n");
#endif
	
	if ((act_readl(UART2_STAT_ADDR) & 0x01) == 0)
	{
#ifdef DEBUG_INFO
	printf("\n UART error! \n");
#endif
		act_writel((act_readl(UART2_STAT_ADDR) | 0x01), UART2_STAT_ADDR);
		return;
	}
	
	irq_keyValue = 0;
	
	while(((act_readl(UART2_STAT_ADDR) >> 5) & 0x01) == 0)
	{
		irq_keyValue = (irq_keyValue << 8) | (act_readl(UART2_RXDAT_ADDR) & 0xff);
	}
	
#ifdef DEBUG_INFO
	printf("\n irq_keyValue = %x \n", irq_keyValue);
#endif	
	
	switch (irq_keyValue) {
		//welcome
		case 0x55555555:
			tp_reset_flag = 1;
			break;		
		
		//touch key
		case 0x56000005:
			cur_key = BUTTON_F1;
			break;
		case 0x56000009:
			cur_key = BUTTON_F4;
			break;
		case 0x56000011:
			cur_key = BUTTON_ESC;
			break;
		case 0x56000021:
			cur_key = BUTTON_TAB;
			break;
		case 0x56000041:
			cur_key = BUTTON_F3;
			break;
		case 0x56000081:
			cur_key = BUTTON_UP;
			break;

		//touch scoll
		case 0x56080001:
			cur_key = BUTTON_F2;
			break;
		case 0x56040001:
			cur_key = BUTTON_F2;
			break;
		case 0x56020001:
			cur_key = BUTTON_F5;
			break;
		case 0x56010001:
			cur_key = BUTTON_F5;
			break;
		case 0x56008001:
			cur_key = BUTTON_TAB;
			break;
		case 0x56004001:
			cur_key = BUTTON_TAB;
			break;
		case 0x56002001:
			cur_key = BUTTON_TAB;
			break;
		case 0x56001001:
			cur_key = BUTTON_TAB;
			break;

		/* default */
		default:
//			printf("bad key_data0 %x in button\n", irq_keyValue);
			irq_keyValue = 0;
			act_writel((act_readl(UART2_STAT_ADDR) | 0x01), UART2_STAT_ADDR);
			return ;
	}
	
	if (save_key)
	{
		if (cur_key != save_key) {
			qstore(save_key | 0x8000);
		}
	}
	save_key = cur_key;
	qstore(cur_key);

	/* mod the key_up timer, so that in a  TICKS_KEY_DOWN_UP later, 
	* there will be a key up message; and if there are continous press downs, there would not 
	* have key up message until there are no press downs*/
	mod_timer(KEY_UP_TIMER, TICKS_KEY_DOWN_UP);
	act_writel((act_readl(UART2_STAT_ADDR) | 0x01), UART2_STAT_ADDR);	
	return ;
}



/*
* we simulate a queue in a arrar buffer, since it's small size, we just shift left  
* when we read the key messages.
*/
INT32U  matrix8_buttons_read( INT32U * buffer, INT32U cnt )
{
	INT32U ind;
	

	if ( is_empty() ) {
		return 0;
	}

	if ( cnt > sizeof_key_buf())
		cnt = sizeof_key_buf() ; 

	for ( ind = 0; ind < cnt; ind++ ) {
		buffer[ind] = qretrieve();	
//		printf("read a key %x\n",buffer[ind]);
	}
	
	return cnt;
}



INT32S matrix8_buttons_init( )
{
	INT32S ret;

	save_key = 0;
	tp_reset_flag = 0;
	init_button_reg();
	
	ret = request_irq(UART2_INTERRUPT_NUM, buttons_irq, 0, DEVICE_NAME, (void *)0);
	if (ret) {
		#ifdef DEBUG_INFO
		printf(" can't request irqs\n");
		#endif
		return ret;
	}
	
	tp_send_reset();
	mdelay(500);
	while(!tp_reset_flag)
	{
		#ifdef DEBUG_INFO
		printf(" can't reset tp! \n");
		#endif
		return -1;
	}
	
	tp_send_synchronous();
	mdelay(500);
	act_writel(0xff, UART2_STAT_ADDR);
	mdelay(100);
	
	init_timer_interrupt();	
	
	return 0;
}

INT32S matrix8_buttons_release()
{
	INT32U flags;

	free_irq(UART2_INTERRUPT_NUM,(void *)0);

	del_timer(KEY_UP_TIMER);	
	return 0;
}

void set_bool_holdkey_pressed(void)
{
	bool_holdkey_pressed = 1;
//	printf(" bool_holdkey_pressed set PMU_LRADC = %x\n", act_readl( PMU_LRADC ) );
}

static void clear_bool_holdkey_pressed(void)
{
		bool_holdkey_pressed = 0;
}

unsigned int is_bool_holdkey_pressed(void)
{
	return bool_holdkey_pressed;
}




/**
 *   按键转化:  对于7键方案,以下函数将MENU长按装换为OK短按
 *              对于9键方案,直接返回0就可以了
 *       
 *   返回值:如果为1,表示该按键不需要转发,0表示需要继续发出
 *
 */

#ifdef KEY_PAD_NUMBER_7

static int keyMenuHacked=0;
static  int  translateKeyMessage(WM_KEY_INFO *keyInfo)
{	
	int retVal=0;

	switch(keyInfo->Key)
	{
		case KEY_MENU:
				switch(keyInfo->PressedCnt)
				{
					case GUI_KEY_MODE_LONG:        //长按MENU 返回上一级
						keyInfo->Key=KEY_MENU;
						keyInfo->PressedCnt=GUI_KEY_MODE_DOWN;	
						keyMenuHacked=1;
						//retVal=1;
						break;
					case GUI_KEY_MODE_DOWN:
						retVal=1;
						break;
					case GUI_KEY_MODE_HOLD:
						if(keyMenuHacked)
							retVal=1;		
						break;
					case GUI_KEY_MODE_UP:    
						if(keyMenuHacked)
						{
							keyInfo->Key=KEY_MENU;
							keyInfo->PressedCnt=GUI_KEY_MODE_UP;	
	
						}else
						{
							S_WM_SendKeyMessage(KEY_OK, GUI_KEY_MODE_DOWN);
							keyInfo->Key=KEY_OK;
							keyInfo->PressedCnt=GUI_KEY_MODE_UP;
						}
						keyMenuHacked=0;
					
						break;
						
					default:
						break;
				}
			break;
		default:
			break;
		
	}

	return retVal;
		
}

#else
    static  int  translateKeyMessage(WM_KEY_INFO *keyInfo)
    {
    
        return 0;
    
    }
    
#endif






drv_Info *GetDrvInfo(void)
{
//	printf("GetDrvInfo is called !\n");
	return &drvinfo;
}




⌨️ 快捷键说明

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