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

📄 keypad.c

📁 微内核软实时操作系统
💻 C
字号:
/*- * Copyright (c) 2005, Kohsuke Ohtani * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors  *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * keypad.c - GBA keypad driver */#include <driver.h>#include <keycode.h>/* Parameters */#define KEYQ_SIZE	32#define KEYPAD_IRQ	12/* Registers for keypad control */#define REG_KEYSTS	(*(volatile uint16_t *)0x4000130)#define REG_KEYCNT	(*(volatile uint16_t *)0x4000132)/* KEY_STS/KEY_CNT */#define KEY_A		0x0001#define KEY_B		0x0002#define KEY_SELECT	0x0004#define KEY_START	0x0008#define KEY_RIGHT	0x0010#define KEY_LEFT	0x0020#define KEY_UP		0x0040#define KEY_DOWN	0x0080#define KEY_R		0x0100#define KEY_L		0x0200#define KEY_ALL		0x03ff/* KEY_CNT value */#define KEYIRQ_EN	0x4000	/* 0=Disable, 1=Enable */#define KEYIRQ_COND	0x8000  /* 0=Logical OR, 1=Logical AND */typedef void (*input_func)(u_char);static int keypad_init();static int keypad_open();static int keypad_close();static int keypad_read();/* * Driver structure */struct driver keypad_drv __driver_entry = {	/* name */	"GBA Keypad",	/* order */	4,	/* init */	keypad_init,};static struct devio keypad_io = {	/* open */	keypad_open,	/* close */	keypad_close,	/* read */	keypad_read,	/* write */	NULL,	/* ioctl */	NULL,	/* event */	NULL,};/* * Key map */static const u_char key_map[] = {	0,	'A',		/* A */	'B',		/* B */	K_TAB,		/* Select */	K_ENTR,		/* Start */	K_RGHT,		/* Right */	K_LEFT,		/* Left */	K_UP,		/* Up */	K_DOWN,		/* Down */	'R',		/* R */	'L',		/* L */};#define KEY_MAX (sizeof(key_map) / sizeof(u_char))static device_t keypad_dev;	/* Device object */static int keypad_irq;		/* Handle for keyboard irq */static int nr_open;		/* Open count */static struct event io_event = EVENT_INIT(io_event, "keypad");static u_char keyq[KEYQ_SIZE];	/* Queue for ascii character */static int q_tail;static int q_head;static input_func input_handler;/* * Keyboard queue operation */#define keyq_next(i)    (((i) + 1) & (KEYQ_SIZE - 1))#define keyq_empty()    (q_tail == q_head)#define keyq_full()     (keyq_next(q_tail) == q_head)/* * Put one charcter on key queue */static void keyq_enqueue(u_char c){	/* Forward key to input handker */	if (input_handler)		input_handler(c);	else {		sched_wakeup(&io_event);		if (keyq_full())			return;		keyq[q_tail] = c;		q_tail = keyq_next(q_tail);	}}/* * Get one character from key queue */static u_char keyq_dequeue(void){	u_char c;	c = keyq[q_head];	q_head = keyq_next(q_head);	return c;}/* * Interrupt service routine */static int keypad_isr(int irq){	uint16_t sts;	sts = ~REG_KEYSTS & KEY_ALL;	if (sts == (KEY_SELECT|KEY_START))		system_reset();	if (sts & KEY_A)		keyq_enqueue('A');	if (sts & KEY_B)		keyq_enqueue('B');	if (sts & KEY_SELECT)		keyq_enqueue(K_TAB);	if (sts & KEY_START)		keyq_enqueue(K_ENTR);	if (sts & KEY_RIGHT)		keyq_enqueue(K_RGHT);	if (sts & KEY_LEFT)		keyq_enqueue(K_LEFT);	if (sts & KEY_UP)		keyq_enqueue(K_UP);	if (sts & KEY_DOWN)		keyq_enqueue(K_DOWN);	if (sts & KEY_R)		keyq_enqueue('R');	if (sts & KEY_L)		keyq_enqueue('L');	return 0;}/* * Open */static int keypad_open(device_t dev, int mode){	if (input_handler)		return EBUSY;	if (nr_open > 0)		return EBUSY;	nr_open++;	return 0;}/* * Close */static int keypad_close(device_t dev){	if (input_handler)		return EBUSY;	if (nr_open != 1)		return EINVAL;	nr_open--;	return 0;}/* * Read */static int keypad_read(device_t dev, char *buf, size_t *nbyte, int blkno){	int rc;	size_t count;	if (input_handler)		return EBUSY;	if (*nbyte == 0)		return 0;	if (keyq_empty()) {		rc = sched_sleep(&io_event);		if (rc == SLP_INTR)			return EINTR;	}	for (count = 0; count < *nbyte; count++) {		if (keyq_empty())			break;		*buf = keyq_dequeue();		buf++;	}	*nbyte = count;	return 0;}/* * Attach input handler for another driver. * * After an input handler is attached, all key event is forwarded * to that handler. */void keypad_attach(void (*handler)(u_char)) {	input_handler = handler;}/* * Initialize */int keypad_init(void){	input_handler = NULL;	keypad_dev = device_create(&keypad_io, "keypad");	ASSERT(keypad_dev);	/* Disable keypad interrupt */	REG_KEYCNT = 0;	/* Setup isr */	keypad_irq = irq_attach(KEYPAD_IRQ, IPL_INPUT, 0, keypad_isr, NULL);	ASSERT(keypad_irq != -1);	/* Enable interrupt for all key */	REG_KEYCNT = KEY_ALL | KEYIRQ_EN;	return 0;}

⌨️ 快捷键说明

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