移动鼠标还是有难度的,先搞清楚键盘事件 获取按键编码更新:int.c #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); /* 通知PIC"IRQ-01已经受理完毕" */
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;
}
io_out8(PIC0_OCW2, 0x61); 作用是通知PIC,IRQ1中断啦! 中断IRQ1的编号是0x61 中断IRQ3的编号是0x63 将“0x60+IRQ号码”输出给OCW2,此时PIC继续监视IRQ1中断是否发生。 如果忘记输出给OCW2,那么PIC不再监视,意味着键盘输入无效 编号0x0060的设备 = 键盘 按下按键之后,会显示出一个数字(十六进制) 松开按键之后,会显示出一个数字(十六进制) 测试:打开cmd,输入make run 加快中断处理目前字符显示的内容被放在了中断处理程序中。这种方式打断CPU本来工作,不再接收别的中断,所以中断速度太慢,出现不连贯的现象 - 先将按键的编码接收
- 保存到变量
- 然后由HariMain偶尔查看该变量
- 如果,发现有数据变动,就显示出来
更新:int.c 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); /*通知PIC IRQ-01已经受理完毕 */
data = io_in8(PORT_KEYDAT);
if (keybuf.flag == 0) {
keybuf.data = data;
keybuf.flag = 1;
}
return;
}
键盘输入时需要缓冲区, 定义了 一个构造体keybuf, 如果flag是0,表示缓冲区为空, 如果flag是1,就表示缓冲区中存有数据。 接下来,通过HariMain功能查看变量,发生变动显示字符。 更新:bootpack.c 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);
}
}
由于作者创建的缓冲区只能存储一个字节,而ctrl是两个字节,所以按下和松开ctrl键的时候只显示第一个字节,恰巧第一个字节又相同,所以看起来没反应。 制作FIFO缓冲区解决方法就是扩展缓冲区大小。 之前说过,缓冲区有两种方式 FIFO属于第一个进去,第一个出来 FILO属于第一个进去,最后一个出来
而这次是希望输入ABC输出ABC,所以用FIFO输出方式. 更新:int.c struct KEYBUF {
unsigned char data[32]; /*缓冲区大小设置*/
int next;
};
void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0x61); /* 通知PIC IRQ-01已经受理完毕 */
data = io_in8(PORT_KEYDAT);
if (keybuf.next < 32) {
keybuf.data[keybuf.next] = data;
keybuf.next++;
}
return;
}
更新:bootpack.c void HariMain(void)
{
....脑补代码
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);
}
}
}
- 如果在禁止中断的期间里做数据移送处理会出现问题。
- 如果在数据移送处理前,允许中断的话,会搞乱处理的数据。
那该怎么办才好呢? 优化FIFO缓冲区能不能开发一个不需要数据移送操作的FIFO型缓冲区呢? 答案是可以的 原理如下: 数据读出位置追上数据写入位置的时候,就相当于缓冲区为空,没有数据 要维护下一个要写入数据的位置, 还要维护下一个要读出数据的位置。 更新:bootpack.c struct KEYBUF {
unsigned char data[32];
int next_r ,next_w;
int len; /*缓冲区能记录多少字节的数据*/
};
更新:int.c void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0x61); /* 通知 IRQ-01已经受理完毕 */
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;
}
这样,FIFO缓冲区设置完毕 整理FIFO缓冲区鼠标每次移动就会连续发送3个字节的数据。 我们已经掌握了键盘发送2个字节的方法,所以发送3个字节也不在话下。 FIFO缓冲区结构可以移植到鼠标 更新:bootpack.h,增加内容 struct FIFO8 {
unsigned char *buf;
int p, q, size, free, flags;
};
新建:fifo.c,初始化fifo void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
/* 初始化FIFO缓冲区 */
{
fifo->size = size;
fifo->buf = buf;
fifo->free = size; /* 缓冲区的大小 */
fifo->flags = 0;
fifo->p = 0; /* 下一个数据写入位置 */
fifo->q = 0; /* 下一个数据读出位置 */
return;
}
更新:fifo.c ,增加put功能(缓冲区存储信息) .....代码省略
#define FLAGS_OVERRUN 0x0001
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
/* 向FIFO传送数据并保存 */
{
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;
}
更新:fifo.c ,增加get功能(缓冲区读取信息) int fifo8_get(struct FIFO8 *fifo)
/* 从FIFO取得一个数据 */
{
int data;
if (fifo->free == fifo->size) {
/* 如果缓冲区为空,则返回 -1 */
return -1;
}
data = fifo->buf[fifo->q];
fifo->q++;
if (fifo->q == fifo->size) {
fifo->q = 0;
}
fifo->free++;
return data;
}
更新:fifo.c ,增加status功能(缓冲区状态查询) int fifo8_status(struct FIFO8 *fifo)
/* 报告一下到底积攒了多少数据 */
{
return fifo->size - fifo->free;
}
功能写好了,想要使用,先放入int.c struct FIFO8 keyfifo;
void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0x61); /* 通知PIC,说IRQ-01的受理已经完成 */
data = io_in8(PORT_KEYDAT);
fifo8_put(&keyfifo, data);
return;
}
最后再放入bootpack.c char s[40], mcursor[256], keybuf[32];
fifo8_init(&keyfifo, 32, keybuf);
for (;;) {
io_cli();
if (fifo8_status(&keyfifo) == 0) {
io_stihlt();
} else {
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);
}
}
折腾了这么久,鼠标还是不能动!!! 鼠标想让鼠标移动? 先让控制电路有效 再让鼠标事件有效 鼠标控制电路包含在键盘控制电路里, 如果键盘控制电路的初始化正常完成, 鼠标电路控制器的激活也就完成了。 更新:bootpack.c #define PORT_KEYDAT 0x0060
#define PORT_KEYSTA 0x0064
#define PORT_KEYCMD 0x0064
#define KEYSTA_SEND_NOTREADY 0x02
#define KEYCMD_WRITE_MODE 0x60
#define KBC_MODE 0x47
void wait_KBC_sendready(void)
{
/* 等待键盘控制电路准备完毕 */
for (;;) {
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
break;
}
}
return;
}
void init_keyboard(void)
{
/* 初始化键盘控制电路 */
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, KBC_MODE);
return;
}
wait_KBC_sendready = 让键盘控制电路做好准备动作 init_keyboard = 一边确认可否往键盘控制电路传送信息,一边发送模式设定指令(0x60) 更新:bootpack.c #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; /* 顺利的话,键盘控制其会返送回ACK(0xfa)*/
}
测试:打开cmd,输入make run 鼠标事件触发了,显示了设定的文字 但是,鼠标还是不能移动 从鼠标接收数据现在取出中断数据 更新:int.c struct FIFO8 mousefifo;
void inthandler2c(int *esp)
/* 来自PS/2鼠标的中断 */
{
unsigned char data;
io_out8(PIC1_OCW2, 0x64); /* 通知PIC1 IRQ-12的受理已经完成 */
io_out8(PIC0_OCW2, 0x62); /* 通知PIC0 IRQ-02的受理已经完成 */
data = io_in8(PORT_KEYDAT);
fifo8_put(&mousefifo, data);
return;
}
更新:bootpack.c,鼠标数据取得方法 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);
}
}
}
测试:打开cmd,make run 随着鼠标的移动,变量一直在变化! 鼠标还是不能移动! 硬件交互难度很大,细品! 今天就到此,明天继续!
|