《30天自制操作系统》读书笔记Day17
2013-10-07 20:16
447 查看
1.创建命令行窗口
把命令行作为一个新的任务加入操作系统。也不再需要B0~B2了。
添加窗体并删掉B0~B2:
然后是命令行任务:
这样就将窗口创建好了。但是现在激活的窗口还是任务A的窗口,想要在按Tab键时将命令行窗口激活。
其实切换窗口就是让窗口标题栏的颜色更改。
将窗口标题栏描绘代码和描绘窗口剩余部分的代码分开:
接着修改bootpack.c:
2.实现命令行中字符串的输入
要实现命令行字符的输入,只需要在按键时向命令行任务发送FIFO数据即可。为了方便,把FIFO结构体放在TASK中:
接下来修改HariMain,根据key_to的值向task_cons的FIFO发送数据:
然后修改console_task让它能够接收并处理键盘数据,并且把&fifo改成&task->fifo:
运行系统,按Tab键后即可在命令行窗口中进行输入。
接下来实现shift按键输入其他符号功能。
运行系统发现shift的按键编码如下:
准备一个key_shift变量记录shift状态,并且使用两个按键编码到字符编码的转换表(分别用于按下时与不按时)。
运行即可实现键盘上基本所有符号的输入。
最后,尝试实现大小写。
已知大小写规则如下:
即CapsLock和Shift状态相同时输入小写,其余为大写。
CapsLock状态已经通过asmhead.nas获取,保存在binfo->leds中:
修改HariMain以实现小写输入:
3.对锁定键的支持
前面已经能够读取大小写锁定的状态了,这里尝试对3种锁定的支持。这里不具体描述步骤了,太麻烦了,上传了一份文件:i8042_键盘.pdf
把命令行作为一个新的任务加入操作系统。也不再需要B0~B2了。
添加窗体并删掉B0~B2:
sht_cons = sheet_alloc(shtctl); buf_cons = (unsigned char *) memman_alloc_4k(memman, 256 * 165); sheet_setbuf(sht_cons, buf_cons, 256, 165, -1); /* 没有透明色 */ make_window8(buf_cons, 256, 165, "console", 0); make_textbox8(sht_cons, 8, 28, 240, 128, COL8_000000); task_cons = task_alloc(); task_cons->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8; task_cons->tss.eip = (int) &console_task; task_cons->tss.es = 1 * 8; task_cons->tss.cs = 2 * 8; task_cons->tss.ss = 1 * 8; task_cons->tss.ds = 1 * 8; task_cons->tss.fs = 1 * 8; task_cons->tss.gs = 1 * 8; *((int *) (task_cons->tss.esp + 4)) = (int) sht_cons; task_run(task_cons, 2, 2); /* level=2, priority=2 */ sheet_slide(sht_back, 0, 0); sheet_slide(sht_cons, 32, 4); sheet_slide(sht_win, 64, 56); sheet_slide(sht_mouse, mx, my); sheet_updown(sht_back, 0); sheet_updown(sht_cons, 1); sheet_updown(sht_win, 2); sheet_updown(sht_mouse, 3);
然后是命令行任务:
void console_task(struct SHEET *sheet) { struct FIFO32 fifo; struct TIMER *timer; struct TASK *task = task_now(); int i, fifobuf[128], cursor_x = 8, cursor_c = COL8_000000; fifo32_init(&fifo, 128, fifobuf, task); timer = timer_alloc(); timer_init(timer, &fifo, 1); timer_settime(timer, 50); for (;;) { io_cli(); if (fifo32_status(&fifo) == 0) { task_sleep(task); io_sti(); } else { i = fifo32_get(&fifo); io_sti(); if (i <= 1) { //光标用定时器 if (i != 0) { timer_init(timer, &fifo, 0); cursor_c = COL8_FFFFFF; } else { timer_init(timer, &fifo, 1); cursor_c = COL8_000000; } timer_settime(timer, 50); boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43); sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44); } } } }
这样就将窗口创建好了。但是现在激活的窗口还是任务A的窗口,想要在按Tab键时将命令行窗口激活。
其实切换窗口就是让窗口标题栏的颜色更改。
将窗口标题栏描绘代码和描绘窗口剩余部分的代码分开:
void make_window8(unsigned char *buf, int xsize, int ysize, char *title, char act) { boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0 ); boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 ); boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1); boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2); boxfill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2); boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1); boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3); boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2); boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1); make_wtitle8(buf, xsize, title, act); return; } void make_wtitle8(unsigned char *buf, int xsize, char *title, char act) { static char closebtn[14][16] = { "OOOOOOOOOOOOOOO@", "OQQQQQQQQQQQQQ$@", "OQQQQQQQQQQQQQ$@", "OQQQ@@QQQQ@@QQ$@", "OQQQQ@@QQ@@QQQ$@", "OQQQQQ@@@@QQQQ$@", "OQQQQQQ@@QQQQQ$@", "OQQQQQ@@@@QQQQ$@", "OQQQQ@@QQ@@QQQ$@", "OQQQ@@QQQQ@@QQ$@", "OQQQQQQQQQQQQQ$@", "OQQQQQQQQQQQQQ$@", "O$$$$$$$$$$$$$$@", "@@@@@@@@@@@@@@@@" }; int x, y; char c, tc, tbc; if (act != 0) { tc = COL8_FFFFFF; tbc = COL8_000084; } else { tc = COL8_C6C6C6; tbc = COL8_848484; } boxfill8(buf, xsize, tbc, 3, 3, xsize - 4, 20); putfonts8_asc(buf, xsize, 24, 4, tc, title); for (y = 0; y < 14; y++) { for (x = 0; x < 16; x++) { c = closebtn[y][x]; if (c == '@') { c = COL8_000000; } else if (c == '$') { c = COL8_848484; } else if (c == 'Q') { c = COL8_C6C6C6; } else { c = COL8_FFFFFF; } buf[(5 + y) * xsize + (xsize - 21 + x)] = c; } } return; }
接着修改bootpack.c:
if (i == 256 + 0x0f) /* Tab */ { if (key_to == 0) //key_to用于记录键盘数据发送到哪个窗口 { key_to = 1; make_wtitle8(buf_win, sht_win->bxsize, "task_a", 0); make_wtitle8(buf_cons, sht_cons->bxsize, "console", 1); } else { key_to = 0; make_wtitle8(buf_win, sht_win->bxsize, "task_a", 1); make_wtitle8(buf_cons, sht_cons->bxsize, "console", 0); } sheet_refresh(sht_win, 0, 0, sht_win->bxsize, 21); sheet_refresh(sht_cons, 0, 0, sht_cons->bxsize, 21); }
2.实现命令行中字符串的输入
要实现命令行字符的输入,只需要在按键时向命令行任务发送FIFO数据即可。为了方便,把FIFO结构体放在TASK中:
struct TASK { int sel, flags; //sel用于存放GDT的编号 struct TSS32 tss; int priority; //优先级 int level; struct FIFO32 fifo; };
接下来修改HariMain,根据key_to的值向task_cons的FIFO发送数据:
if (i <= 511 && i >=256) //键盘数据 { sprintf(s, "%02X", i - 256); putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2); if (i < 256 + 0x54 && keytable[i - 256] != 0)//一般字符 { if (key_to == 0) //发送给任务A { if (cursor_x < 128) { s[0] = keytable[i - 256 ]; s[1] = 0; putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1); cursor_x += 8; } } else //发送到命令行 { fifo32_put(&task_cons->fifo, keytable[i-256]+256); } } if (i == 256 + 0x0e ) //退格 { if (key_to ==0)//任务A { if (cursor_x > 8) { putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, " ", 1); cursor_x -= 8; } } else fifo32_put(&task_cons->fifo, 8 + 256); } if (i == 256 + 0x0f) /* Tab */ { if (key_to == 0) { key_to = 1; make_wtitle8(buf_win, sht_win->bxsize, "task_a", 0); make_wtitle8(buf_cons, sht_cons->bxsize, "console", 1); } else { key_to = 0; make_wtitle8(buf_win, sht_win->bxsize, "task_a", 1); make_wtitle8(buf_cons, sht_cons->bxsize, "console", 0); } sheet_refresh(sht_win, 0, 0, sht_win->bxsize, 21); sheet_refresh(sht_cons, 0, 0, sht_cons->bxsize, 21); } //光标再显示 boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43); sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44); }
然后修改console_task让它能够接收并处理键盘数据,并且把&fifo改成&task->fifo:
void console_task(struct SHEET *sheet) { struct TIMER *timer; struct TASK *task = task_now(); int i, fifobuf[128], cursor_x = 16, cursor_c = COL8_000000; char s[2]; fifo32_init(&task->fifo, 128, fifobuf, task); timer = timer_alloc(); timer_init(timer, &task->fifo, 1); timer_settime(timer, 50); //显示提示符 putfonts8_asc_sht(sheet, 8, 28, COL8_FFFFFF, COL8_000000, ">", 1); for (;;) { io_cli(); if (fifo32_status(&task->fifo) == 0) { task_sleep(task); io_sti(); } else { i = fifo32_get(&task->fifo); io_sti(); if (i <= 1) { //光标用定时器 if (i != 0) { timer_init(timer, &task->fifo, 0); cursor_c = COL8_FFFFFF; } else { timer_init(timer, &task->fifo, 1); cursor_c = COL8_000000; } timer_settime(timer, 50); } if (256 <= i && i <=511)//键盘数据 { if (i == 8 + 256) { if (cursor_x > 16) { putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, " ", 1); cursor_x -= 8; } } else { if (cursor_x < 240) { s[0] = i - 256; s[1] = 0; putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, s, 1); cursor_x += 8; } } } boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43); sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44); } } }
运行系统,按Tab键后即可在命令行窗口中进行输入。
接下来实现shift按键输入其他符号功能。
运行系统发现shift的按键编码如下:
按下 抬起 左shift 0x2a 0xaa 右shift 0x36 0xb
准备一个key_shift变量记录shift状态,并且使用两个按键编码到字符编码的转换表(分别用于按下时与不按时)。
static char keytable0[0x80] = { 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']', 0, 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '\'', '`', 0, '\\', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c,0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, }; static char keytable1[0x80] = { 0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', 0, 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0, 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', '~', 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c,0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, }; int key_shift = 0; if (i <= 511 && i >=256) //键盘数据 { sprintf(s, "%02X", i - 256); putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2); if (i < 0x80 + 256) { if (key_shift ==0) { s[0] = keytable0[i - 256]; } else s[0] = keytable1[i - 256]; } else s[0] = 0; if (s[0] != 0) { if (key_to == 0) //发送给任务A { if (cursor_x < 128) { s[1] = 0; putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1); cursor_x += 8; } } else //发送到命令行 { fifo32_put(&task_cons->fifo, s[0] + 256); } } if (i == 256 + 0x0e ) //退格 { if (key_to ==0)//任务A { if (cursor_x > 8) { putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, " ", 1); cursor_x -= 8; } } else fifo32_put(&task_cons->fifo, 8 + 256); } if (i == 256 + 0x0f) /* Tab */ { if (key_to == 0) { key_to = 1; make_wtitle8(buf_win, sht_win->bxsize, "task_a", 0); make_wtitle8(buf_cons, sht_cons->bxsize, "console", 1); } else { key_to = 0; make_wtitle8(buf_win, sht_win->bxsize, "task_a", 1); make_wtitle8(buf_cons, sht_cons->bxsize, "console", 0); } sheet_refresh(sht_win, 0, 0, sht_win->bxsize, 21); sheet_refresh(sht_cons, 0, 0, sht_cons->bxsize, 21); } if (i == 256 + 0x2a) //左shift按下 { key_shift |= 1; } if (i == 256 + 0x36) //右shift按下 { key_shift |= 2; } if (i == 256 + 0xaa) //左shift松开 { key_shift &= ~1; } if (i == 256 + 0xb6) //右shift松开 { key_shift &= ~2; } //光标再显示 boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43); sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44); }
运行即可实现键盘上基本所有符号的输入。
最后,尝试实现大小写。
已知大小写规则如下:
CapsLock 为 OFF & Shift 为 OFF --> 小写英文字母 CapsLock 为 ON & Shift 为 ON --> 小写英文字母 CapsLock 为 OFF & Shift 为 ON --> 大写英文字母 CapsLock 为 ON & Shift 为 OFF --> 大写英文字母
即CapsLock和Shift状态相同时输入小写,其余为大写。
CapsLock状态已经通过asmhead.nas获取,保存在binfo->leds中:
binfo->leds 第4位 ----->ScrollLock状态 binfo->leds 第5位 ----->NumLockLock状态 binfo->leds 第6位 ----->CapsLock状态
修改HariMain以实现小写输入:
int key_leds = (binfo->leds >> 4) & 7; if ('A' <= s[0] && s[0] <= 'Z') { if (((key_leds & 4) == 0 && key_shift == 0) || ((key_leds & 4) != 0 && key_shift != 0)) { s[0] += 0x20;//将大写字母转换为小写 } }
3.对锁定键的支持
前面已经能够读取大小写锁定的状态了,这里尝试对3种锁定的支持。这里不具体描述步骤了,太麻烦了,上传了一份文件:i8042_键盘.pdf
#define KEYCMD_LED 0xed /* 需要发送的LED数据 */ struct FIFO32 keycmd; /* 用来存放向键盘发送的命令 */ int keycmd_buf[32]; int keycmd_wait = -1; fifo32_init(&keycmd, 32, keycmd_buf, 0); /* 初始化键盘命令缓冲区 */ /* 为了避免和键盘当前状态冲突,在一开始先进行设置 */ fifo32_put(&keycmd, KEYCMD_LED); fifo32_put(&keycmd, key_leds); /* 所有对键盘LED的设置都是对键盘中的一块芯片8048的设置 */ /* 不是以前设置的i8042,但是通过i8042间接的对8048进行设置 */ /* 详见我上传的资源:i8042_键盘.pdf */ if (fifo32_status(&keycmd) > 0 && keycmd_wait < 0) { /* 如果存在要向键盘发生的数据,则发送它 */ keycmd_wait = fifo32_get(&keycmd); /* 取出数据 */ wait_KBC_sendready(); /* 清空i8042的输入缓冲区 */ io_out8(PORT_KEYDAT, keycmd_wait); /* 向0x60端口发生0xed */ /* 发生了该命令之后,需要继续向0x60端口发生LED设置字节 */ /* 在下面等待确认是否有按下控制LED灯的键后来决定LED设置字节的值,然后再发生 */ } if (i == 256 + 0x3a) { /* CapsLock */ key_leds ^= 4; /* key_leds中标识CapsLock的bit位取反 */ fifo32_put(&keycmd, KEYCMD_LED); /* 向i8042发生命令来修改8048 */ fifo32_put(&keycmd, key_leds); /* 改变CapsLock等的状态 */ } if (i == 256 + 0x45) { /* NumLock */ key_leds ^= 2; /* 和CapsLock类似的处理 */ fifo32_put(&keycmd, KEYCMD_LED); fifo32_put(&keycmd, key_leds); } if (i == 256 + 0x46) { /* ScrollLock */ key_leds ^= 1; /* 和CapsLock类似的处理 */ fifo32_put(&keycmd, KEYCMD_LED); fifo32_put(&keycmd, key_leds); } /* 0xfa是ACK信息 */ if (i == 256 + 0xfa) { /* 键盘成功接收到数据 */ keycmd_wait = -1; /* 等于-1表示可以发送指令 */ } if (i == 256 + 0xfe) { /* 键盘没有成功接收到数据 */ wait_KBC_sendready(); io_out8(PORT_KEYDAT, keycmd_wait); /* 重新发送上次的指令 */ }
相关文章推荐
- 《30天自制操作系统》17_day_学习笔记
- 读书笔记《30天自制操作系统》day06
- 读书笔记《30天自制操作系统》day14
- 《30天自制操作系统》读书笔记Day15
- 《30天自制操作系统》08_day_学习笔记
- 内存管理(30天自制操作系统--读书笔记)
- 读书笔记《30天自制操作系统》day04
- 读书笔记《30天自制操作系统》day08
- 读书笔记《30天自制操作系统》day05
- 《30天自制操作系统》09_day_学习笔记
- 《30天自制操作系统》14_day_学习笔记
- 多定时器处理2(30天自制操作系统 -- 读书笔记)
- 《30天自制操作系统》18_day_学习笔记
- 多定时器处理3(30天自制操作系统 -- 读书笔记)
- 读书笔记《30天自制操作系统》day09
- 读书笔记《30天自制操作系统》day10
- 《30天自制操作系统》读书笔记Day4
- 《30天自制操作系统》01_day_学习笔记
- 《30天自制操作系统》06_day_学习笔记
- 读书笔记《30天自制操作系统》day01