3 鼠标解读(2)(harib05c)

程序已经很清晰了,我们继续解读程序。首先对mouse_decode函数略加修改。

bootpack.c 节选

  1. struct MOUSE_DEC {
  2. unsigned char buf[3], phase;
  3. int x, y, btn;
  4. };
  5. int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
  6. {
  7. if (mdec->phase == 0) {
  8. /* 等待鼠标的0xfa的阶段 */
  9. if (dat == 0xfa) {
  10. mdec->phase = 1;
  11. }
  12. return 0;
  13. }
  14. if (mdec->phase == 1) {
  15. /* 等待鼠标第一字节的阶段 */
  16. if ((dat & 0xc8) == 0x08) {
  17. /* 如果第一字节正确 */
  18. mdec->buf[0] = dat;
  19. mdec->phase = 2;
  20. }
  21. return 0;
  22. }
  23. if (mdec->phase == 2) {
  24. /* 等待鼠标第二字节的阶段 */
  25. mdec->buf[1] = dat;
  26. mdec->phase = 3;
  27. return 0;
  28. }
  29. if (mdec->phase == 3) {
  30. /* 等待鼠标第三字节的阶段 */
  31. mdec->buf[2] = dat;
  32. mdec->phase = 1;
  33. mdec->btn = mdec->buf[0] & 0x07;
  34. mdec->x = mdec->buf[1];
  35. mdec->y = mdec->buf[2];
  36. if ((mdec->buf[0] & 0x10) != 0) {
  37. mdec->x |= 0xffffff00;
  38. }
  39. if ((mdec->buf[0] & 0x20) != 0) {
  40. mdec->y |= 0xffffff00;
  41. }
  42. mdec->y = - mdec->y; /* 鼠标的y方向与画面符号相反 */
  43. return 1;
  44. }
  45. return -1; /* 应该不会到这儿来 */
  46. }

■■■■■

结构体里增加的几个变量用于存放解读结果。这几个变量是x、y和btn,分别用于存放移动信息和鼠标按键状态。

另外,笔者还修改了if(mdec—>phase==1)语句。这个if语句,用于判断第一字节对移动有反应的部分是否在0~3的范围内;同时还要判断第一字节对点击有反应的部分是否在8~F的范围内。如果这个字节的数据不在以上范围内,它就会被舍去。

虽说基本上不这么做也行,但鼠标连线偶尔也会有接触不良、即将断线的可能,这时就会产生不该有的数据丢失,这样一来数据会错开一个字节。数据一旦错位,就不能顺利解读,那问题可就大了。而如果添加上对第一字节的检查,就算出了问题,鼠标也只是动作上略有失误,很快就能纠正过来,所以笔者加上了这项检查。

■■■■■

最后的if(mdec—>phase==3)部分,是解读处理的核心。鼠标键的状态,放在buf[0]的低3位,我们只取出这3位。十六进制的0x07相当于二进制的0000 0111,因此通过与运算(&),可以很顺利地取出低3位的值。

x和y,基本上是直接使用buf[1]和buf[2] ,但是需要使用第一字节中对鼠标移动有反应的几位(参考第一节的叙述)信息,将x和y的第8位及第8位以后全部都设成1,或全部都保留为0。这样就能正确地解读x和y。

在解读处理的最后,对y的符号进行了取反的操作。这是因为,鼠标与屏幕的y方向正好相反,为了配合画面方向,就对y符号进行了取反操作。

■■■■■

这样,鼠标数据的解读就完成了。现在我们来修改一下显示部分。

HariMain 节选

  1. } else if (fifo8_status(&mousefifo) != 0) {
  2. i = fifo8_get(&mousefifo);
  3. io_sti();
  4. if (mouse_decode(&mdec, i) != 0) {
  5. /* 数据的3个字节都齐了,显示出来 */
  6. sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
  7. if ((mdec.btn & 0x01) != 0) {
  8. s[1] = 'L';
  9. }
  10. if ((mdec.btn & 0x02) != 0) {
  11. s[3] = 'R';
  12. }
  13. if ((mdec.btn & 0x04) != 0) {
  14. s[2] = 'C';
  15. }
  16. boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
  17. putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
  18. }
  19. }

虽然程序中会检查mdec.btn的值,用3个if语句将s的值置换成相应的字符串,不过这一部分,暂时先不要管了。这样,程序就变成以下这样。

  1. sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
  2. boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
  3. putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);

这与以前的程序很相似,仅仅用来显示字符串。现在加上刚才的if语句:

  1. if ((mdec.btn & 0x01) != 0) {
  2. s[1] = 'L';
  3. }

这行程序的意思是,如果mdec.btn的最低位是1,就把s的第2个字符(注:第1个字符是s[0] )换成‘L’。这就是将小写字符置换成大写字符。其他的if语句也都这样理解吧。

■■■■■

执行一下看看。

3 鼠标解读(2)(harib05c) - 图1
移动鼠标 点击鼠标

反应都很正常,心情大好。