30天自制操作系统-第07天-FIFO与鼠标控制

1.鼠标按键编码(/07_day/hrib04a)

1)中断处理函数:

#define PORT_KEYDAT 0x0060   

void inthandler21(void)

{

    ......

unsigned s[4];

io_out8(PIC0_OCW2,0x61);/*通知PIC  IRQ_01以及受理完毕   0x60 + IRQ号*/ 

data = io_in8(PORT_KEYDAT); //读取键盘编码 端口0x60

sprintf(s,"%02X",data);//格式化键盘编码为16进制串

putfonts8_asc(binfo->vram,binfo->scrnx,0,16,COL8_FFFFFF,s);//显示键盘编码16进制

}

 注意:读出的是扫描码

2)HariMain函数片段:

{

......

for (;;) {
io_cli();
if (keybuf.flag == 0) {
io_stihlt();/*sti,hlt 这两条指令之间的中断不受理*/
} 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);
}
}

}

2. 完善FIFO队列(07_day/harib04e/fifo.c)

使用一个先进先出的队列记录数据(键盘或鼠标以及其他设备产生的),加快处理速度

  1)队列结构定义

struct FIFO8 { unsigned char *buf; int p, q, size, free, flags; };

  2)队列初始化

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; /* 下一个数据读出位置*/
}

3)写队列函数

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;
}
 4)读队列函数 

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;
}

5)队列状态函数

int fifo8_status(struct FIFO8 *fifo)
/* 报告一下积攒的数据量, */
{
return fifo->size - fifo->free;
}

  

3.鼠标初始化

1)鼠标有效

  鼠标控制电路(包含在键盘控制电路里),鼠标本身

2)鼠标键盘控制电路准备

void wait_KBC_sendready(void)
{
/* 等待键盘控制电路准备完毕 */
for (;;) {
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
//从设备号码0x0064处读取数据的倒数第2位为0时,说明键盘控制电路可以接收CPU指令了
break;
}
}
return;
}

3)初始化键盘

void init_keyboard(void)
{
/* 初始化键盘控制电路 */
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);//设定指令模式为0x60
wait_KBC_sendready();
io_out8(PORT_KEYDAT, KBC_MODE);//设定鼠标模式
return;
}
4)鼠标激活 

void enable_mouse(void)
{
/* 激活鼠标*/
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
//向键盘控制电路写入0xd4后,下一个数据就会自动发送给鼠标
wait_KBC_sendready();
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);//使鼠标能够使用,成功的话向CPU发送一个0xfa作为答复。
return; /*键盘控制其会返回ACK */
}
4.从鼠标接收数据

 1)鼠标处理中断

struct FIFO8 mousefifo;

void inthandler2c(int *esp)
/* 来自PS/2鼠标的中断 */
{
unsigned char data;
io_out8(PIC1_OCW2, 0x64); /* 通知PIC IRQ-12 已经受理完毕 */
io_out8(PIC0_OCW2, 0x62); /* 通知PIC IRQ-02 已经受理完毕 */
data = io_in8(PORT_KEYDAT);
fifo8_put(&mousefifo, data);
return;
}

2)鼠标数据接收(与键盘代码一样)

fifo8_init(&mousefifo,128,mousebuf);//鼠标数据量大,队列设置为128字节

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);
}
}
}

 

posted @   煮酒熬码  阅读(91)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示