平台

处理器:Intel Celeron(R) Dual-Core CPU

操作系统:Windows7 专业版 x86

阅读书籍:《30天自制操作系统》—川合秀实[2015.03.23 ]

将《30天自制操作系统》简称为“书”。对于书中的工具,可以专门对其笔记学习。

工具:../toolset/

1 解读鼠标数据

1.1 鼠标3字节数据含义

每当鼠标中断发生时,鼠标会向鼠标控制电路回复3字节数据,CPU通过IN指令从鼠标电路设备端口中读取这些数据。这3字节的含义分别为:

  • 第一字节的低3位表鼠标键状态,bit[0]为1表鼠标左击,bit[1]为1表鼠标右击,bit[2]为1表鼠标点击滑轮;(低4位只在点击鼠标(左中右)时才会发生变化,在8~ F范围内变化,鼠标第一字节的高4位在0~3范围内变化,具体含义见解读鼠标数据的程序);
  • 鼠标的第二字节与鼠标左右移动有关系;
  • 鼠标第三个字节与鼠标上下移动有关系。

判断第一字节高4位是否在0~ 3的范围内,同时判断第一字节低4位是否在8~ F的范围内,这样就可以避免鼠标接触不良产生数据丢失时对错位数据的解析。

1.2 解读鼠标数据

(1) 描述鼠标数据的结构体

struct MOUSE_DEC {unsigned char buf[3], phase;    //鼠标3字节数据,用于读取鼠标3字节变量int x, y, btn;                 //(x, y)用于存解读到的移动信息,btn存点击信息
};

(2) 读取缓冲区3字节数据解析显示

/*获取鼠标3字节数据,读到3字节数据时解读它们
*mdec存储鼠标3字节数据和解读结果
*dat表示从缓冲区读来的3字节数据
*/
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{if (mdec->phase == 0) {//激活鼠标时鼠标回复的内容if (dat == 0xfa) {mdec->phase = 1;}return 0;}if (mdec->phase == 1) {//鼠标第1字节内容if ((dat & 0xc8) == 0x08) {//11001000,//判断第1个字节高4位是否在0~3范围内,//判断第1个字节低4位是否在8~F范围内mdec->buf[0] = dat;mdec->phase = 2;}return 0;}if (mdec->phase == 2) {//鼠标第2字节内容mdec->buf[1] = dat;mdec->phase = 3;return 0;}if (mdec->phase == 3) {//鼠标第3字节内容mdec->buf[2] = dat;mdec->phase = 1;mdec->btn = mdec->buf[0] & 0x07;    //得到鼠标按键状态mdec->x = mdec->buf[1];            //鼠标x方向移动数据mdec->y = mdec->buf[2];            //鼠标y方向移动移动if ((mdec->buf[0] & 0x10) != 0) {mdec->x |= 0xffffff00; //第一字节bit[4]为1时,x方向坐标高24位为1}if ((mdec->buf[0] & 0x20) != 0) {mdec->y |= 0xffffff00; //第一字节bit[5]为1时,y方向坐标高24位为1}mdec->y = - mdec->y; //鼠标的y方向与画面符号相反return 1;}return -1;//错误时mdec->phase != 0时返回
}

修改激活鼠标的函数,使鼠标回应的0xfa数据在这里得到标记。如果不提前让mdec->phase= 0,mouse_decode()函数就会返回-1。

#define KEYCMD_SENDTO_MOUSE      0xd4
#define MOUSECMD_ENABLE         0xf4void enable_mouse(struct MOUSE_DEC *mdec)
{//鼠标有效wait_KBC_sendready();io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);wait_KBC_sendready();io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);//成功后0xfa会被发送过来mdec->phase = 0; //舍掉0xfa的标记return;
}

将这些函数和结构体加入bootpack.c中,访问缓冲区部分的程序变为:

enable_mouse(&mdec);//不断查询缓冲区,如果有数据,将缓冲区内的数据显示完为止for (;;) {io_cli(); //查看缓冲区时,屏蔽中断if (fifo8_status(&mousefifo) == 0) {io_stihlt(); //如果缓冲区内无数据则开启中断并让CPU休眠,直到中断唤醒} else {data = fifo8_get(&mousefifo);io_sti(); //开启中断if (mouse_decode(&mdec, data) != 0) {//显示解读到的鼠标数据sprintf(str, "[lcr %4d %4d]", mdec.x, mdec.y);if ((mdec.btn & 0x01) != 0) {str[1] = 'L';}if ((mdec.btn & 0x02) != 0) {str[3] = 'R';}if ((mdec.btn & 0x04) != 0) {str[2] = 'C';}boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 32, 16, 32 + 15 * 8 - 1, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, str);}}}

编译运行此时的操作系统程序,得到如下结果:

Figure1. 解读到的鼠标操作的数据

请根据显示的数据跟鼠标移动结合理解解读出来的数据。它表示鼠标x和y方向上相对于前一刻坐标的变化值。


2 移动鼠标图标

2.1 鼠标坐标处理

int  mx, my;mx = (binfo->scrnx - 16) / 2;
my = (binfo->scrny - 28 - 16) / 2;mx += mdec.x;
my += mdec.y;
if (mx < 0) {mx = 0;
}
if (my < 0) {my = 0;
}
if (mx > binfo->scrnx - 16) {mx = binfo->scrnx - 16;
}
if (my > binfo->scrny - 16) {my = binfo->scrny - 16;
}

如果鼠标的坐标超出了屏幕范围,则做特殊处理。

2.2 移动鼠标

//隐藏上次鼠标移动留下的痕迹
boxfill8(binfo->vram, binfo->scrnx, COL8_000000, mx, my, mx + 15, my + 15);
/*…鼠标坐标处理…*/sprintf(str, "(%3d, %3d)", mx, my);
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);

往bootpack.c中加入鼠标移动的代码,主函数的代码如下(主函数代码过长,要被整理了撒):

void HariMain(void)
{int    data;int    mx, my;char str[30];char    mcursor[256];char   mousebuf[128];            //接收鼠标数据缓冲区struct MOUSE_DEC mdec;struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;//初始化GDT和IDTinit_gdtidt();//初始化PICinit_pic();//屏蔽所有中断io_sti();fifo8_init(&mousefifo, 32, mousebuf);    io_out8(PIC0_IMR, 0xfb); io_out8(PIC1_IMR, 0xef); //初始化鼠标控制电路init_keyboard();//初始化调色板init_palette();//初始化屏幕颜色init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);putfonts8_asc(binfo->vram, binfo->scrnx, 110, 60, COL8_FFFFFF, "oh Still Haribote OS.");mx = (binfo->scrnx - 16) / 2;my = (binfo->scrny - 28 - 16) / 2;//初始化鼠标显示init_mouse_cursor8(mcursor, COL8_000000);//激活鼠标enable_mouse(&mdec);//不断查询缓冲区,如果有数据,将缓冲区内的数据显示完为止for (;;) {io_cli(); //查看缓冲区时,屏蔽中断if (fifo8_status(&mousefifo) == 0) {io_stihlt(); //如果缓冲区内无数据则开启中断并让CPU休眠,直到中断唤醒} else {data = fifo8_get(&mousefifo);io_sti(); //开启中断if (mouse_decode(&mdec, data) != 0) {//获得解读到的鼠标坐标sprintf(str, "[lcr %4d %4d]", mdec.x, mdec.y);if ((mdec.btn & 0x01) != 0) {str[1] = 'L';}if ((mdec.btn & 0x02) != 0) {str[3] = 'R';}if ((mdec.btn & 0x04) != 0) {str[2] = 'C';}boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 0, 32 + 15 * 8 - 1, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, str);boxfill8(binfo->vram, binfo->scrnx, COL8_000000, mx, my, mx + 15, my + 15);//隐藏上次鼠标移动留下的痕迹mx += mdec.x;my += mdec.y;if (mx < 0) {mx = 0;}if (my < 0) {my = 0;}if (mx > binfo->scrnx - 16) {mx = binfo->scrnx - 16;}if (my > binfo->scrny - 16) {my = binfo->scrny - 16;}sprintf(str, "(%3d, %3d)", mx, my);putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);}}}}

打开“!cons_nt.bat”编译成功后,使用“makerun”命令在QEMU中运行得鼠标移动的结果:

Figure2. 鼠标移动1

Figure3. 鼠标移动2

3 总结

[1] 鼠标控制电路在键盘控制电路中,读取鼠标发送数据的端口号为0x0060。

[2] 通过初始化鼠标控制电路激活鼠标时,鼠标会给鼠标控制电路回复oxfa数据,会触发鼠标中断函数。鼠标中断发生时会连续向鼠标控制电路发送3个连续字节。所以,鼠标中断函数内不可包含复杂的处理,否则中断函数往缓冲区存储的数据就不对。

[3] 可以通过PIC指定鼠标中断的中断号。

[4] mouse_move。

[x86OS] Note Over.

[2015.04.17]

[Rx86OS-IX] 解读鼠标数据 移动鼠标相关推荐

  1. 大数据挑战赛-鼠标轨迹识别

    声明:本文属于原创,如想转载,请务必在抬头注明出处. 大数据挑战赛-鼠标轨迹识别,竞赛官网:http://bdc.saikr.com/c/cql/34541 1.我们看一下整个竞赛的详情 赛题描述 鼠 ...

  2. 使用libusb读取鼠标数据

    使用libusb读取鼠标数据 文章目录 使用libusb读取鼠标数据 1. HID协议 1.1 描述符 1.2 数据格式 1.2.1 键盘 1.2.2 LED 1.2.3 鼠标 1.2.4 扫描码 2 ...

  3. flex 表格勾选后 鼠标滚动会自动勾选_外设Show 篇四十五:办公鼠里的BBA做工如何,罗技MX Anywhere 3鼠标体验_鼠标...

    2020-11-12 21:28:093点赞7收藏0评论 如果把罗技M905算作鼻祖的话,那么MX Anywhere系列到现在已经上市十一年了.作为高端无线办公鼠标的代表,办公外设里的BBA,罗技MX ...

  4. C#获取鼠标位置,模拟鼠标,模拟键盘(多方转载)

    c#获取鼠标坐标 很多时候我们需要用到鼠标在相对于窗体上的坐标,或者相对于屏幕的坐标,这里就把我的经验记录下. 用Control.MousePosition获得当前鼠标的坐标CurrentPoint, ...

  5. php控制鼠标,HTML_用VBS控制鼠标的实现代码(获取鼠标坐标、鼠标移动、鼠标单击、鼠标双击、鼠标右击),怎么用VBS模拟鼠标左键单击、 - phpStudy...

    用VBS控制鼠标的实现代码(获取鼠标坐标.鼠标移动.鼠标单击.鼠标双击.鼠标右击) 怎么用VBS模拟鼠标左键单击.左键双击.右键单击?-- 网上搜到的答案普遍是VBS无法实现,或者是要用第三方COM( ...

  6. 高招攻略 领英助你清晰解读大数据专业

    至顶网CIO与应用频道 06月28日 北京消息:走下高考的竞技场,又走上高招的棋局,2017年的准大学生们正在做一道人生中至关重要的选择题--专业选择.目前经济结构升级和科学技术进步将大数据专业带入了 ...

  7. 【观点见解】解读大数据的5个误区

    [观点见解]解读大数据的5个误区 大数据并不会给你带来大麻烦,事实上,大数据能够帮助你尽量减少业务问题,还能帮助你作出战略性决策.但如果不搞清楚对大数据的一些误区,也可能会给你带来不必要的麻烦.下面就 ...

  8. 根据坐标点鼠标 不移动_CAD移动鼠标时,鼠标右下角有坐标提示,怎么取消?...

    好课推荐: 1.CAD2014:点击查看2.室内&全屋:点击查看3.CAD2019:点击查看4.CAD2018:点击查看5.[bim]revit:点击查看6.室内手绘:点击查看7.CAD三维: ...

  9. WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件

    在WPF中,只有鼠标位置在某个控件上的时候才会触发该控件的鼠标事件. 例如,有两个控件都注册了MouseDown和MouseUp事件,在控件1上按下鼠标,不要放开,移动到控件2上再放开. 在这个过程中 ...

最新文章

  1. 用Python解密2021年最新富豪榜,马云居然连前三都没进
  2. MVC,MVP 和 MVVM 的图示
  3. 数据库中的时间数据在页面显示时后面会多一个.0的问题
  4. nyoj 1261 音痴又音痴的LT(离散化+树状数组求K小数)
  5. php 函数 数组 难学,php 数组的常用函数
  6. Spark源码系列(五)分布式缓存
  7. 《MySQL必知必会》学习笔记——第三章(了解数据库和表)
  8. 2022年电工杯B题应急物资配送问题浅析
  9. 论文笔记 -- ISSCC-2020: GANPU (Multi-DNN Processor for GANs with Speculative Dual-Sparsity Exploitation)
  10. 【C++】队列优先队列详解——deque.queue.priority_queue
  11. 命令行看不见光标怎么办
  12. 我的世界java1.16.3村庄种子,我的世界2020年最新版村庄种子
  13. 宋鸿兵在《货币战争5》中谈到的美国医疗
  14. Python 手把手实现M3U8视频抓取
  15. STM32F10xxx中文板参考手册PDF(内有英文版链接)
  16. 【Excel】忘记VBA密码怎么办(Hex编辑器)
  17. Java华容道小游戏源码分析
  18. 顶级操盘手是怎样准确把握入场时机的
  19. 学习啦!--MHK在线学习小程序 计算机毕业设计
  20. 【正则】正则匹配 QQ号, 邮箱email,手机号码新号段,生日

热门文章

  1. JSP住宅小区物业管理系统(源代码+开题报告+论文+答辩PPT)
  2. python selenium对象怎么序列化_Python Selenium如何操作Cookies
  3. python-下载某短视频平台视频(高清无水印)
  4. 华为mate20能升级鸿蒙系统,华为Mate20最新喜讯,华为EMUI新版本,可以申请更新了...
  5. 用c写一个hello woed
  6. 鸿蒙系统开放吗,鸿蒙系统开放时间敲定!6月2日正式发布,旗舰手机率先升级...
  7. VScode两步实现less自动编译
  8. CLTPHP内容管理系统5.5发布
  9. 【阿不】深入ASP.NET数据绑定(下)—多样的绑定方式
  10. BeautifulSoup搜索节点的几种方法