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

📄 swkbd.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. *//* * swkbd.c - GBA software keyboard driver *//*- * This driver emulates a generic keyboard by using GBA keypad. * * <Key assign> * * On-screen keyboard: * *  A        : Select pointed key *  B        : Enter key *  Select   : Hide keyboard *  Start    :  *  Right    : Move keyboard cursor right *  Left     : Move keyboard cursor left *  Up       : Move keyboard cursor up *  Down     : Move keyboard cursor down *  Button R : Toggle shift state *  Button L : Toggle shift state * * No on-screen keyboard: * *  A        : A key *  B        : B key *  Select   : Show keyboard *  Start    : Enter key *  Right    : Right key *  Left     : Left key *  Up       : Up key *  Down     : Down key *  Button R : R key *  Button L : L Key * */#include <driver.h>#include <keycode.h>#include "lcd.h"#include "kbd_img.h"#include "keymap.h"extern void keypad_attach(void (*handler)(u_char));/* Parameters */#define KBDQ_SIZE	128/* * Since GBA does not kick interrupt for the button release, we have * to wait for a while after button is pressed. Otherwise, many key * events are queued by one button press. */#define CURSOR_WAIT	100	/* 100 msec */#define BUTTON_WAIT	200	/* 200 msec */static int kbd_init();static int kbd_open();static int kbd_close();static int kbd_read();static void move_cursor(void);/* * Driver structure */struct driver kbd_drv __driver_entry = {	/* name */	"GBA S/W Keyboard",	/* order */	11,	/* init */	kbd_init,};static struct devio kbd_io = {	/* open */	kbd_open,	/* close */	kbd_close,	/* read */	kbd_read,	/* write */	NULL,	/* ioctl */	NULL,	/* event */	NULL,};static device_t kbd_dev;	/* Device object */static struct timer kbd_tmr;static int nr_open;		/* Open count */static struct event io_event = EVENT_INIT(io_event, "kbd");static u_char kbdq[KBDQ_SIZE];	/* Queue for ascii character */static int q_tail;static int q_head;/* Meta key status */static int shift;static int alt;static int ctrl;static int capslk;static int kbd_on;static int kbd_page;static volatile int ignore_key;static u_int pos_x, pos_y;static int cur_obj;		/* Current object for cursor *//* * Keyboard queue operation */#define kbdq_next(i)    (((i) + 1) & (KBDQ_SIZE - 1))#define kbdq_empty()    (q_tail == q_head)#define kbdq_full()     (kbdq_next(q_tail) == q_head)/* * Put one charcter on kbd queue */static void kbdq_enqueue(u_char c){	sched_wakeup(&io_event);	if (kbdq_full())		return;	kbdq[q_tail] = c;	q_tail = kbdq_next(q_tail);}/* * Get one character from kbd queue */static u_char kbdq_dequeue(void){	u_char c;	c = kbdq[q_head];	q_head = kbdq_next(q_head);	return c;}/* * Select keyboard page. * *   Page0 ... Text only *   Page1 ... Text & Normal keyboard *   Page2 ... Text & Shifted keyboard */static void kbd_select(int page){	if (page == 0)		REG_DISPCNT = 0x0840;	/* only BG3 */	else if (page == 1) {		REG_DISPCNT = 0x1A40;	/* use BG1&3 */		move_cursor();	} else {		REG_DISPCNT = 0x1C40;	/* use BG2&3 */		move_cursor();	}	kbd_page = page;}/* * Toggle keyboard type: normal or shift. */static void kbd_toggle(){	int page;	if (kbd_page == 0)		return;	if (capslk) 		page = shift ? 1 : 2;	else		page = shift ? 2 : 1;	kbd_select(page);}/* * Timer call back handler. * Just clear ignoring flag. */static void kbd_timeout(u_long tmp){	ignore_key = 0;}/* * Move cursor to point key. */static void move_cursor(void){	uint16_t *oam = OAM;	struct _key_info *ki;	int i, x, y;	ki = (struct _key_info *)&key_info[pos_y][pos_x];	x = ki->pos_x + 108;	y = pos_y * 8 + 11;	i = 0;	switch (ki->width) {	case 9: i = 0; break;	case 11: i = 1; break;	case 12: i = 2; break;	case 13: i = 3; break;	case 15: i = 4; break;	case 17: i = 5; break;	case 19: i = 6; break;	case 53: i = 7; break;	}	if (i != cur_obj) {		oam[cur_obj * 4] = (uint16_t)((oam[cur_obj * 4] & 0xff00) | 160);		oam[cur_obj * 4 + 1] = (uint16_t)((oam[cur_obj * 4 + 1] & 0xfe00) | 240);		cur_obj = i;	}	oam[i * 4] = (uint16_t)((oam[i * 4] & 0xff00) | y);	oam[i * 4 + 1] = (uint16_t)((oam[i * 4 + 1] & 0xfe00) | x);}/* * Process key press */static void key_press(void){	struct _key_info *ki;	u_char ac;	ki = (struct _key_info *)&key_info[pos_y][pos_x];	ac = ki->normal;	/* Check meta key */	switch (ac) {	case K_SHFT:		shift = !shift;		kbd_toggle();		return;	case K_CTRL:		ctrl = !ctrl;		return;	case K_ALT:		alt = !alt;		return;	case K_CAPS:		capslk = !capslk;		kbd_toggle();		return;	}	/* Check ctrl & shift state */	if (ctrl) {		if (ac >= 'a' && ac <= 'z')			ac = ac - 'a' + 0x01;		else if (ac == '\\')			ac = 0x1c;		else			ac = 0;	} else if (kbd_page == 2)		ac = ki->shifted;	if (ac == 0)		return;	/* Check caps lock state */	if (capslk) {		if (ac >= 'A' && ac <= 'Z')			ac += 'a' - 'A';		else if (ac >= 'a' && ac <= 'z')			ac -= 'a' - 'A';	}	/* Check alt key */	if (alt)		ac |= 0x80;	/* Insert key to queue */	kbdq_enqueue(ac);	/* Reset meta status */	if (shift) {		shift = 0;		kbd_toggle();	}	if (ctrl)		ctrl = 0;	if (alt)		alt = 0;}/* * Open */static int kbd_open(device_t dev, int mode){/* * XXX: Temporary allow the multiple device open for different * task until tty driver or tty server is available. * An application may not get the correct keyboard data if * two or more threads reads at same tome. */#if 0	if (nr_open > 0)		return EBUSY;#endif	nr_open++;	return 0;}/* * Close */static int kbd_close(device_t dev){#if 0	if (nr_open != 1)		return EINVAL;#endif	nr_open--;	return 0;}/* * Read */static int kbd_read(device_t dev, char *buf, size_t *nbyte, int blkno){	int rc;	size_t count;	if (*nbyte == 0)		return 0;	if (kbdq_empty()) {		rc = sched_sleep(&io_event);		if (rc == SLP_INTR)			return EINTR;	}	for (count = 0; count < *nbyte; count++) {		if (kbdq_empty())			break;		*buf = kbdq_dequeue();		buf++;	}	*nbyte = count;	return 0;}/* * Input handler * * This routine will be called by keypad ISR. */static void kbd_input(u_char ch){	int move = 0;	int timeout = BUTTON_WAIT;	if (ignore_key)		return;	/* Select key */	if (ch == K_TAB) {		kbd_on = !kbd_on;		kbd_select(kbd_on);		/* Reset meta status */		shift = 0;		alt = 0;		ctrl = 0;		capslk = 0;		goto out;	}	/* Direct input */	if (!kbd_on) {		kbdq_enqueue(ch);		goto out;	}	switch (ch) {	case K_LEFT:		if (pos_x > 0) {			if (pos_y == 4 && pos_x >=4 && pos_x <= 8) /* Space */				pos_x = 3;			pos_x--;			move = 1;		}		break;	case K_RGHT:		if (pos_x < max_x[pos_y]) {			if (pos_y == 4 && pos_x > 3 && pos_x <= 7) /* Space */				pos_x = 8;			pos_x++;			move = 1;		}		break;	case K_UP:		if (pos_y > 0 ) {			pos_y--;			move = 1;			if (pos_x > max_x[pos_y])				pos_x = max_x[pos_y];		}		break;	case K_DOWN:		if (pos_y < 4) {			pos_y++;			move = 1;			if (pos_x > max_x[pos_y])				pos_x = max_x[pos_y];		}		break;	case 'A':		key_press();		break;	case 'B':		kbdq_enqueue(K_ENTR);		break;	case 'R':	case 'L':		shift = shift ? 0 : 1;		kbd_toggle();		break;	case K_ENTR:#ifdef CONFIG_KDUMP		kernel_dump(1);	/* Thread dump */		kernel_dump(2);	/* Thread dump */		kernel_dump(7);	/* VM dump */#endif		break;	}	if (move) {		timeout = CURSOR_WAIT;		move_cursor();	}out:	ignore_key = 1;	timer_timeout(&kbd_tmr, kbd_timeout, 0, timeout);	return;}/* * Init font */static void init_kbd_image(void){	uint8_t bit;	uint16_t val1, val2;	uint16_t *pal = BG_PALETTE;	uint16_t *tile1 = KBD1_TILE;	uint16_t *tile2 = KBD2_TILE;	uint16_t *map1 = KBD1_MAP;	uint16_t *map2 = KBD2_MAP;	int i, j, row, col;	/* Load tiles for keyboard image */	for (i = 0; i < 32; i++)		tile1[i] = 0;	for (i = 0; i < 64 * 12; i++) {		bit = 0x01;		for (j = 0; j < 4; j++) {			val1 = kbd1_bitmap[i] & bit ? 0xff : 0x03;			val2 = kbd2_bitmap[i] & bit ? 0xff : 0x03;			bit = bit << 1;			val1 |= kbd1_bitmap[i] & bit ? 0xff00 : 0x0300;			val2 |= kbd2_bitmap[i] & bit ? 0xff00 : 0x0300;			bit = bit << 1;			tile1[i * 4 + 32 + j] = val1;			tile2[i * 4 + j] = val2;		}	}	/* Setup map */	i = 1;	for (row = 1; row < 7; row++) {		for (col = 13; col < 29; col++) {			map1[row * 32 + col] = (uint16_t)i;			map2[row * 32 + col] = (uint16_t)(i + 127);			i++;		}	}	pal[3] = RGB(0,0,31);	/* Kbd bg color */	pal[255] = RGB(28,28,28);	/* Kbd color */	/* Setup video */	REG_BG1CNT = 0x1284;	/* Size0, 256color, priority0 */	REG_BG2CNT = 0x1484;	/* Size0, 256color, priority0 */	kbd_select(1);}/* * Initialize keyboard cursor */static void init_cursor(void){	int i, j;	uint8_t bit;	uint16_t val;	uint16_t *oam = OAM;	uint16_t *cur = CURSOR_DATA;	uint16_t *pal = SPL_PALETTE;		/* Move out all objects */	for (i = 0; i < 128; i++) {		oam[0] = 160;		oam[1] = 240;		oam += 4;	}	/* Load cursor splite */	for (i = 0; i < 64 * 7 + 64 * 8; i++) {		bit = 0x01;		for (j = 0; j < 4; j++) {			val = cursor_bitmap[i] & bit ? 0xff : 0;			bit = bit << 1;			val |= cursor_bitmap[i] & bit ? 0xff00 : 0;			bit = bit << 1;			cur[i * 4 + j] = val;		}	}	/* Setup cursors */	oam = OAM;	for (i = 0; i < 7; i++) {		oam[0] = (uint16_t)(0x6000 + 160); /* 256 color, Horizontal */		oam[1] = (uint16_t)(0x8000 + 240); /* 32x16 */		oam[2] = (uint16_t)(i * 16); /* Tile number */		oam += 4;	}	/* for space key */	oam[0] = 0x6000 + 160; /* 256 color, Horizontal */	oam[1] = 0xC000 + 240; /* 64x32 */	oam[2] = 112;	pal[255] = RGB(31,0,0);	/* cursor color */}/* * Initialize */static int kbd_init(void){	kbd_dev = device_create(&kbd_io, "kbd");	ASSERT(kbd_dev);	nr_open = 0;	ignore_key = 0;	cur_obj = 0;	kbd_on = 1;	kbd_page = 0;	pos_x = 0;	pos_y = 0;	timer_init(&kbd_tmr);	init_cursor();	init_kbd_image();	move_cursor();	/* Hook keypad input */	keypad_attach(kbd_input);	return 0;}

⌨️ 快捷键说明

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