《30天自制操作系统》08_day_学习笔记

harib05a:
  鼠标解读(01)P145 前一天已经让鼠标成功接收数据了,这些数据是什么意思?
  笔者在这一部分来解读数据:让鼠标动起来啊,停在那不动有什么意思啊!
  前面已经知道,鼠标每一次动作都是3个字节数据,为什么是3个。想想也知道:两个坐标,一个状态

if (mouse_phase == 0) {         /* 等待鼠标进入0xfa的状态。实际上就是等待控制器准备就绪 */
  if (i == 0xfa) {
  mouse_phase = 1;
  }
} else if (mouse_phase == 1) {  /* 等待鼠标的第一个字节 */
  mouse_dbuf[0] = i;
  mouse_phase = 2;
} else if (mouse_phase == 2) {  /* 等待鼠标的第二个字节 */
  mouse_dbuf[1] = i;
  mouse_phase = 3;
} else if (mouse_phase == 3) {  /* 等待鼠标的第三个字节 */
  mouse_dbuf[2] = i;
  mouse_phase = 1;
                   /* 将这三个字节显示出来 */
  sprintf(s, "%02X %02X %02X", mouse_dbuf[0], mouse_dbuf[1], mouse_dbuf[2]);
  boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 8 * 8 - 1, 31);
  putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
}

  看了上面的代码,细心的肯定会发现一个问题,鼠标每次动作产生3个字节数据:坐标X、Y、状态信息
  那么0xfa是什么东西?为什么有4个if的条件判断?不是3个字节的数据吗?
  ANS:我们回头看看鼠标中断程序;void enable_mouse(void)。(前一天的内容)发现没有,
      鼠标激活成功会返回一个ACK,这个ACK的值就是0xfa。他表示的意思就是:好的,我已经准备好了发送数据了。
harib05b:
  标题:稍事整理\\这部分没什么新的可讲的代码
  没错:笔者在这里就是对HzriMain做了一些整理;内容完全没有变化(不想看的也可以跳过这一部分)
    1、把解读鼠标所需要的变量整合到结构体MOUSE_DEC中了
    2、在鼠标中断处理程序enable_mouse(void)最后,把0xfa进行了处理,成功就绪返回1,这样便于鼠标数据接收和处理
  MOUSE_DEC{ unsigned char buf[3], phase };

harib05c:
  鼠标解读(02)这里结构体MOUSE_DEC发生了一些变化:

struct MOUSE_DEC { //x,y用来存放鼠标位置信息;btn存放状态信息。
  unsigned char buf[3], phase;
  int x, y, btn;
};
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat) {
  if (mdec->phase == 0) {
  /* 等待鼠标的0xfa状态,接收到enable_mouse(void)的0xfa的ACK值,表示鼠标控制器以及就绪,可以传数据了。 */
  if (dat == 0xfa) {
  mdec->phase = 1;
  }
  return 0;
}
if (mdec->phase == 1) {
  /* 等待鼠标的第一字节状态 */
  if ((dat & 0xc8) == 0x08) {
  /* 对第一个字节的范围进行判断(0-3) */
    mdec->buf[0] = dat;
    mdec->phase = 2;
  }
  return 0;
}
if (mdec->phase == 2) {
  /* 等待鼠标的第二个字节第二个字节的范围(8-F) */
  mdec->buf[1] = dat;
  mdec->phase = 3;
  return 0;
}
if (mdec->phase == 3) {
    /* 第三个字节,最关键的部分,鼠标键的状态放在buf[0]的低3位 */
  mdec->buf[2] = dat;
  mdec->phase = 1;
  mdec->btn = mdec->buf[0] & 0x07; //buf[0]&0000 0111取出buf[0]的低3位,鼠标状态信息
  mdec->x = mdec->buf[1]; //取出鼠标的坐标信息
  mdec->y = mdec->buf[2];
if ((mdec->buf[0] & 0x10) != 0) {  mdec->x |= 0xffffff00;  }
if ((mdec->buf[0] & 0x20) != 0) {  mdec->y |= 0xffffff00;  }
  mdec->y = - mdec->y; /* y坐标的方向,鼠标和画面符号是相反的 */
  return 1;
  }
  return -1; //获取鼠标信息失败了
}

  接下来修改鼠标的显示部分:

//原理:用if语句将s的值置换成相应的字符串即可
if (mouse_decode(&mdec, i) != 0) {
  sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
  if ((mdec.btn & 0x01) != 0) { s[1] = ‘L‘;}
  if ((mdec.btn & 0x02) != 0) { s[3] = ‘R‘;}
  if ((mdec.btn & 0x04) != 0) { s[2] = ‘C‘;}
  boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
  putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
} //接下来输出字符串s就可以了:

harib05d:
  如何让鼠标在屏幕上动起来?
  上面我们已经搞定了鼠标移动时的坐标位置,我们其实已经把鼠标的图像给显示出来了;
  接下来:我们按照这个坐标值,不断的刷新鼠标的显示就行了
  原   理:每次鼠标中断读取的鼠标信息给鼠标图形显示函数putfonts8_asc()
      我们来看看笔者是怎么修改的:

if (mouse_decode(&mdec, i) != 0) {  /* 显示鼠标数据的三个字节 */
    sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
    if ((mdec.btn & 0x01) != 0) {     s[1] = ‘L‘;    } //如果btn的最后一位为1
    if ((mdec.btn & 0x02) != 0) {    s[3] = ‘R‘;     } //如果btn的倒数第三位为1  
    if ((mdec.btn & 0x04) != 0) {     s[2] = ‘C‘;    } //如果btn的倒数第四位为1
    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31); //显示界面下面的白条
    putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);              //鼠标指针的移动
    //这个东西是干嘛的啊??隐藏鼠标
    //当鼠标坐标移到下面的白条的时候。如果上面叠加了鼠标的图像将会变得很乱,
    //在这里,当鼠标位置移到下面的时候,将其位置放在白条的上方
    //就像我们桌面上,鼠标指针移到最下方,始终在任务栏的上方(一个道理)
    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, mx, my, mx + 15, my + 15);
    mx += mdec.x;
    my += mdec.y;
    if (mx < 0) {     mx = 0;    }                                 //检测x坐标越界到最小   if (my < 0) {     my = 0;    }                                 //检测y坐标越界到最小
    if (mx > binfo->scrnx - 16) {     mx = binfo->scrnx - 16;    } //检测x坐标越界到最大
    if (my > binfo->scrny - 16) {     my = binfo->scrny - 16;    } //检测x坐标越界到最大
    sprintf(s, "(%3d, %3d)", mx, my);                   //输出字符串
    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 0, 79, 15); /* 隐藏坐标 */
    putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); /* 显示坐标 */
    putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16); /* 描画坐标 */
}

  还有一点明天再写吧!真心费时间。。。。。。。。。。。

时间: 2024-10-21 16:34:01

《30天自制操作系统》08_day_学习笔记的相关文章

《30天自制操作系统》学习笔记-第1天

为了加深对操作系统的理解,我决定照着<30天自制操作系统>这本书实践一下.项目的github链接是https://github.com/YatesXu/YatesOSASK/ 关于十六进制编辑器 第一个问题就是书中给的十六进制编辑器是日文的,在我的电脑上打开之后是一片乱码,于是我比较之后选用了这个十六进制编辑器wxMEdit,链接是https://wxmedit.github.io/. 另外,visual studio也可以,但是express版不能用,所以还是选用免费开源的软件吧(笑) (伪

《30天自制操作系统》读书笔记(3) 引入C语言

这一次的学习相当曲折, 主要是因为粗心, Makefile里面的错误导致了文件生成出现各种奇奇怪怪的问题, 弄得心力交瘁, 因此制作过程还是尽量按着作者的路子来吧. 作者提供的源码的注释在中文系统下是乱码, 而且代码的分隔用了两个Tab, 在这里要处理一下: :%s/;.*//g 删除所有的注释; :%s/\t\t/\t 把两个Tab替换为一个Tab; 要让作者的nas文件和asm文件拥有相同的语法规则, 在_vimrc文件的最后一行添加 au BufNewFile,BufRead *.nas

《30天自制操作系统》读书笔记(2)hello, world

让系统跑起来 要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实上你用的是U盘还是软盘对我们的操作系统没有影响,缺点是你的U盘刷入系统后容量只能是1440 MB,即当年流行的3.5英寸软盘的大小,当然不用担心,再格式化一次(用DiskGeniu),就可以恢复. 我做事情的话,总是怕自己的努力的结果白费了,害怕辛辛苦苦看完这本书但是发现做出来的东西现在根本没法用,

《30天自制操作系统》读书笔记(4) 绘图

暑假果然是滋生懒散的温床. (╯‵□′)╯︵┻━┻ 好久不动都忘记之前做到哪里了, 上次好像做到了C语言的引入, 这一节所做的东西都相当轻松, 将会绘制出操作系统的基本界面. 绘图的原理 按照书中所说, 将值写入到显存中就能在屏幕上显示相应的像素, 在asmhead.nas 中有这一段: 1 CYLS EQU 0x0ff0 ; 设定启动区 2 LEDS EQU 0x0ff1 3 VMODE EQU 0x0ff2 ; 关于颜色数目的信息,颜色的位数 4 SCRNX EQU 0x0ff4 ; 分辨率

《30天自制操作系统》读书笔记(1)读前感

做一个自己的操作系统, 在我看来一直是不可以思议的,而且奇妙的,像是吉他手亲手打造一把自己的吉他? 似乎这个比喻不太恰当, 但是,感觉是一样的. <30天自制操作系统> 为日本的川和秀实先生所著, 有人说他是 "<XX天学会XXX>之类的书中为数不多的几本好书之一." 这本书的优点非常明显,通俗生趣,甚至于有点啰嗦:而且作者无私地提供了源代码而且允许你以任何方式使用,也提供了编译的所有工具,所有东西都是"开箱即用",不容易出问题. 作为后生我

《30天自制操作系统》读书笔记(5) GDT&amp;IDT

梳理项目结构 项目做到现在, 前头的好多东西都忘了, 还是通过Makefile重新理解一下整个项目是如何编译的: 现在我们拥有这么9个文件: ipl10.nas    InitialProgramLoader, 占用了软盘的第一个扇区并符合启动盘的规范, 默认被载入地址是0x7c00 到 0x7e00, 负责将10个柱面读入到0x8200到0x34fff (10个柱面共10*2*18 = 360 个扇区但是第一个没有被读入); asmhead.nas     包含一些暂时未知的设定; naskf

多定时器处理1(30天自制操作系统--读书笔记)

自认为写过很多MCU程序,但总是回头想想,我所了解的MCU编程思想大体有两种,其中具体的想法我得再找时间写下来. 总想总结出一个可扩展的,易移植的写法,但能力还没到这个层次.但<30天自制操作系统>这本书确实给我了一个思路,就像我已经写过的两篇读书笔记. 将两个独立的内容--FIFO和内存动态管理做到高度模块化,尤其是其中数据结构模型的设计更是我学习的好例子. 今天要学习的设计内容是多定时器处理.原书对这部分的处理讲的很详细,由浅入深,看得我由衷佩服作者,也可能是因为我水平低,稍稍看出点门道来

单字节的FIFO缓存(30天自制操作系统--读书笔记)

从今天起,写一些读书笔记.最近几个月都在看<30天自制操作系统这本书>,书虽说看的是电子书,但可以花钱买的正版书,既然花费了金钱,就总得有些收获. 任何人都不能总是固步自封,想要进步就得学习别人的知识,对于程序员而言,最简单的方法即是学习别人的代码. 今天的标题是“单字节的FIFO缓存”,其实就是做一个FIFO,看名字就知道了.也就4个函数和1个相关结构体,这样的小代码在嵌入式系统中很常用,也会很好用. 1.相关数据结构体 struct FIFO8 { unsigned char *buf;

《30天自制操作系统》笔记(12)——多任务入门

<30天自制操作系统>笔记(12)——多任务入门 进度回顾 上一篇介绍了设置显示器高分辨率的方法.本篇讲一下操作系统实现多任务的方法. 什么是多任务 对程序员来说,也许这是废话,不过还是说清楚比较好. 多任务就是让电脑同时运行多个程序(如一边写代码一边听音乐一边下载电影). 电脑的CPU只有固定有限的那么一个或几个,不可能真的同时运行多个程序.所以就用近似的方式,让多个程序轮换着运行.当轮换速度够快(0.01秒),给人的感觉就是"同时"运行了. 多任务之不实用版 我们首先从

《30天自制操作系统》笔记(03)——使用Vmware

<30天自制操作系统>笔记(03)--使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测试和U盘启动的一些问题.本篇就来解决之. 遇到的问题 物理机测试 简单来说,把软盘(U盘)做成启动盘后,自然想要用来启动物理机器.毕竟这才是真正的测试.(用QEMU总没多大的成就感)但物理机测试的麻烦在于太慢了,每次都要关掉Windows,重启,测试,然后再重启Windows.而且还没办法截图. 而用Vmwa