1.获取按键编码
鼠标与键盘在代码实现上相差不大,所以我们只要完成其中一个就可以仿制出另一个。 因为之前按一个键后,其余什么也做不了。 修改init.c中inthandler21函数
#define PORT_KEYDAT 0x0060
void inthandler21(int *esp)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
unsigned char data, s[4];
io_out8(PIC0_OCW2, 0x61);
data = io_in8(PORT_KEYDAT);
sprintf(s, "%02X", data);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
return;
}
2.加快中断处理
上文程序的缺点是字符显示的内容被放在中断处理程序中。如果处理键盘的中断速度太慢,就会出现鼠标的运动不连贯,不能从网上接受数据等。所以我们可以先将按键编码保存到变量,然后由main函数偶尔去检查这个变量,有就显示。 所以修改之前的函数如下:
struct KEYBUF {
unsigned char data, flag;
};
#define PORT_KEYDAT 0x0060
struct KEYBUF keybuf;
void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0x61);
data = io_in8(PORT_KEYDAT);
if (keybuf.flag == 0) {
keybuf.data = data;
keybuf.flag = 1;
}
return;
}
对于main函数:
for (;;) {
io_cli();
if (keybuf.flag == 0) {
io_stihlt();
} else {
i = keybuf.data;
keybuf.flag = 0;
io_sti();
sprintf(s, "%02X", i);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
}
}
3.制作FIFO缓冲区
前者写出的程序只能存储一个字节,下面准备做一个存储多字节的缓冲区,这样不会马上存满。 最简单的就是在KEYBUF结构体里增加data变量(后果是程序变得冗长)
struct KEYBUF {
unsigned char data1, data2, data3, data4, ...
};
struct KEYBUF {
unsigned char data[4];
};
struct KEYBUF {
unsigned char data[32];
int next;
};
void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0x61);
data = io_in8(PORT_KEYDAT);
if (keybuf.next < 32) {
keybuf.data[keybuf.next] = data;
keybuf.next++;
}
return;
}
4.改善FIFO缓冲区
此节的目标是开发一个不需要数据移送操作的FIFO型缓冲区。大致流程就是一边读一边写,当读出与写入一致,说明缓冲区为空,当到数据末尾,则置零,重头开始。
struct KEYBUF {
unsigned char data[32];
int next_r, next_w, len;
};
void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0x61);
data = io_in8(PORT_KEYDAT);
if (keybuf.len < 32) {
keybuf.data[keybuf.next_w] = data;
keybuf.len++;
keybuf.next_w++;
if (keybuf.next_w == 32) {
keybuf.next_w = 0;
}
}
return;
}
for (;;) {
io_cli();
if (keybuf.len == 0) {
io_stihlt();
} else {
i = keybuf.data[keybuf.next_r];
keybuf.len--;
keybuf.next_r++;
if (keybuf.next_r == 32) {
keybuf.next_r = 0;
}
io_sti();
sprintf(s, "%02X", i);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
}
}
5.整理FIFO缓冲区
由于鼠标每次移动会连续发送3个字节数据。现在将缓冲区定义成(字节数)可变的。
struct FIFO8 {
unsigned char *buf;
int p, q, size, free, flags;
};
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
{
fifo->size = size;
fifo->buf = buf;
fifo->free = size;
fifo->flags = 0;
fifo->p = 0;
fifo->q = 0;
return;
}
#define FLAGS_OVERRUN 0x0001
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
{
if (fifo->free == 0) {
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->p] = data;
fifo->p++;
if (fifo->p == fifo->size) {
fifo->p = 0;
}
fifo->free--;
return 0;
}
int fifo8_get(struct FIFO8 *fifo)
{
int data;
if (fifo->free == fifo->size) {
return -1;
}
data = fifo->buf[fifo->q];
fifo->q++;
if (fifo->q == fifo->size) {
fifo->q = 0;
}
fifo->free++;
return data;
int fifo8_status(struct FIFO8 *fifo)
{
return fifo->size - fifo->free;
}
6.总算讲到鼠标了
鼠标中断号:IRQ12 要让鼠标中断有效需要实现下面俩个装置有效: ①鼠标控制电路有效 ②鼠标本身有效
#define KEYCMD_SENDTO_MOUSE 0xd4
#define MOUSECMD_ENABLE 0xf4
void enable_mouse(void)
{
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
return;
}
7.从鼠标接收数据
中断做好,下面就从中断中取出数据。(可以类比键盘)
struct FIFO8 mousefifo;
void inthandler2c(int *esp)
{
unsigned char data;
io_out8(PIC1_OCW2, 0x64);
io_out8(PIC0_OCW2, 0x62);
data = io_in8(PORT_KEYDAT);
fifo8_put(&mousefifo, data);
return;
}
fifo8_init(&mousefifo, 128, mousebuf);
for (;;) {
io_cli();
if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
io_stihlt();
} else {
if (fifo8_status(&keyfifo) != 0) {
i = fifo8_get(&keyfifo);
io_sti();
sprintf(s, "%02X", i);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
} else if (fifo8_status(&mousefifo) != 0) {
i = fifo8_get(&mousefifo);
io_sti();
sprintf(s, "%02X", i);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 47, 31);
putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
}
}
}
ok,今天就完成了键盘与鼠标的终端操作,明天继续呼呼。
|